javaIO流
1.File类的使用
FIle类的一个对象,代表一个文件或一个文件目录(俗称:文件夹)
如何实例化?
public File(String pathname)
以pathname为路径创建File对象,可以是绝对路径或者相对路径,如果pathname是相对路径,则默认的当前路径在系统属性user.dir中存储。
绝对路径:是一个固定的路径,从盘符开始
相对路径:是相对于某个位置开始
public File(String parent,String child) 以parent为父路径,child为子路径创建File对象。
public File(File parent,String child) 根据一个父File对象和子文件路径创建File对象
File file = new File("hello.txt");//相对路径 单元测试中相对于当前Module
File file1 = new File("D:\\programme\\java\\java\\java01\\hi.txt"); //绝对路径
路径中的每级目录之间用一个路径分隔符隔开。路径分隔符和系统有关:
windows和DOS系统默认使用 “ \ ” 来表示
UNIX和URL使用 “/ ” 来表示
Java程序支持跨平台运行,因此路径分隔符要慎用。为了解决这个隐患,File类提供了一个常量:
public static final String separator。根据操作系统,动态的提供分隔符。
public class FileTest {
@Test
public void test(){
File file = new File("hello.txt");//相对路径 相对于当前Module
File file1 = new File("D:\\programme\\java\\java\\java01\\hi.txt"); //绝对路径
// 此时仅仅是两个内存中的对象而已
System.out.println(file);
System.out.println(file1);
File file2 = new File("D:\\programme\\java\\java", "java01");
System.out.println(file2);
File file3 = new File(file2, "h2.txt");
System.out.println(file3);
}
}
File类的使用
public String getAbsolutePath():获取绝对路径
public string getPath() :获取路径
public string getName() :获取名称
public string getParent():获取上层文件目录路径。若无,返回null
public long length():获取文件长度(即:字节数)。不能获取目录的长度。
public long lastModified():获取最后一次的修改时间,毫秒值
public string[] list():获取指定目录下的所有文件或者文件目录的名称数组
public File[] listFiles():获取指定目录下的所有文件或者文件目录的File数组
public boolean renameTo(File dest):把文件重命名为指定的文件路径
public class FileTest {
@Test
public void test(){
//public String getAbsolutePath():获取绝对路径
//public string getPath() :获取路径
//public string getName() :获取名称
//public string getParent():获取上层文件目录路径。若无,返回null
//public long length():获取文件长度(即:字节数)。不能获取目录的长度。
//public long lastModified():获取最后一次的修改时间,毫秒值
File file = new File("hello.txt");//相对路径 相对于当前Module
File file1 = new File("D:\\programme\\hi.txt"); //绝对路径
System.out.println(file.getAbsoluteFile());
System.out.println(file.getPath());
System.out.println(file.getName());
System.out.println(file.getParent());
System.out.println(file.length());
System.out.println(file.lastModified());
System.out.println();
System.out.println(file1.getAbsoluteFile());
System.out.println(file1.getPath());
System.out.println(file1.getName());
System.out.println(file1.getParent());
System.out.println(file1.length());
System.out.println(file1.lastModified());
}
}
public class FileTest {
@Test
public void test(){
//public string[] list():获取指定目录下的所有文件或者文件目录的名称数组
File file = new File("D:\\programme");
for (String s : file.list()) {
System.out.println(s);
}
//public File[] listFiles():获取指定目录下的所有文件或者文件目录的File数组
for (File listFile : file.listFiles()) {
System.out.println(listFile);
}
/*
public boolean renameTo(File dest):把文件重命名为指定的文件路径比如:
file1.renameTo(file2)为例:
要想保证返回true,需要file1在硬盘中是存在的,且file2不能在硬盘中存在。*/
File file1 = new File( "hello.txt" );
File file2 = new File( "D: \\io\\lhi.txt" );
boolean renameTo = file2.renameTo(file1);
System.out.println(renameTo);
}
}
public boolean isDirectory():判断是否是文件目录
public boolean isFile() :判断是否是文件
public boolean exists() :判断是否存在
public boolean canRead() :判断是否可读
public boolean canwrite() :判断是否可写
public boolean isHidden() :判断是否隐藏
//File类的创建 创建硬盘中对应的文件或文件目录
public boolean createNewFile():创建文件。若文件存在,则不创建,返回false
public boolean mkdir() :创建文件目录。如果此文件目录存在,就不创建了。如果此文件目录的上层目录不存在,也不创建。
public boolean mkdirs():创建文件目录。如果上层文件目录不存在,一并创建
//删除磁盘中的文件或文件目录
public boolean deLete( ):删除文件或者文件夹
//删除注意事项: Java中的删除不走回收站。
File类中涉及到关于文件或文件目录的创建、删除、重命名、修改时间、文件大小等方法,并未涉及到写入或读取文件内容的操作。如果需要读取或写入文件内容,必须使用IO流来完成。
后续File类的对象常会作为参数传递到流的构造器中,指明读取或写入的"终点".
2.IO流原理及流的分类
IO是Input/Output的缩写,I/O技术是非常实用的技术,用于处理设备之间的数据传输。如读/写文件,网络通讯等。Java程序中,对于数据的输入/输出操作以“流(stream)”的方式进行。
按操作数据单位不同分为:字节流(8 bit),字符流(16 bit)
按数据流的流向不同分为:输入流,输出流
按流的角色的不同分为:节点流,处理流
IO流体系
3.节点流
Filereader
public class myTest {
//读入的文件一定要存在,否则就会抱FileNotFoundException.
@Test
public void test(){
FileReader fileReader = null;
try{
//1.实例化File类的对象,指明要操作的文件
File file = new File("hello.txt");
//2.提供具体的流
fileReader = new FileReader(file);
//3.数据的读入
//方式一
// int date = fileReader.read();
// while(date != -1){
// System.out.print((char)date);
// date = fileReader.read();
// }
//方式二
int date;
// read():返回读入的一个字符,如果达到文件末尾,返回-1
while((date = fileReader.read()) != -1){
System.out.print((char)date);
}}catch (Exception e){
e.printStackTrace();
}finally {
//4.流的关闭操作
try {
if(fileReader!=null){
fileReader.close();
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
对read()操作升级:使用read的重载方法
read(char[] cbuf):返回每次读入cbuf数组中的字符的个数,如果达到文件末尾,返回-1.
public class myTest {
//read(char[] cbuf):返回每次读入cbuf数组中的字符的个数,如果达到文件末尾,返回-1.
@Test
public void test(){
FileReader fileReader = null;
try{//1.File类的实例化
File file = new File("hello.txt");
//2.FileReader流的实例化
fileReader = new FileReader(file);
//3.读入的操作
char[] cbuffer = new char[5];
int len;
while((len = fileReader.read(cbuffer)) != -1){
//错误的写法
// for(int i = 0;i<cbuffer.length;i++){
// System.out.print(cbuffer[i]);
// helloworld123ld
// }
// 正确的写法:
// for(int i = 0;i<len;i++){
// System.out.print(cbuffer[i]);
// }
// 正确的写法:
String s = new String(cbuffer, 0, len);
System.out.print(s);
}}catch (Exception e){
e.printStackTrace();
}finally {
if(fileReader != null){
//4.资源的关闭
try {
fileReader.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
}
Filewriter
public class myTest {
/**
* 如果文件不存在,在输出的过程中,会自动创建此文件
* 如果存在,
* 如果使用的构造器是:Filewriter(file,false)/Filewriter(file):对原有文件的覆盖
* 如果使用的构造器是:Filewriter(file,true):不会对原有文件覆盖,会在源有文件的基础上增加内容
*/
@Test
public void testFilewriter(){
FileWriter fileWriter = null;
try {
//1.提供File类的对象,指明写出到的文件
File file = new File("hello1.txt");
//2.提供Filewriter的对象,用于数据的写出
fileWriter = new FileWriter(file);
//3.写出的操作
fileWriter.write("I have a deeam!\n");
fileWriter.write("you are to have a deram");
}catch (Exception e){
e.printStackTrace();
}finally {
//4.资源的关闭
try {
fileWriter.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
对于文本文件(.txt .java .c .cpp),使用字符流处理
对于非文本文件(.jpg .mp3 .mp4 .ovi .doc .ppt),使用字节流处理
FileInputStream/FileOutputStream
public class myTest {
@Test
public void testFileInputstream(){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
try {
File file = new File("1.png");
File file2 = new File("2.png");
fileInputStream = new FileInputStream(file);
fileOutputStream = new FileOutputStream(file2);
byte[] bytes = new byte[5];
int len;
while ((len = fileInputStream.read(bytes)) != -1) {
fileOutputStream.write(bytes, 0, len);
}
}catch (Exception e){
e.printStackTrace();
}finally {
try {
if(fileInputStream != null){
fileInputStream.close();
}
} catch (Exception e) {
e.printStackTrace();
}
if(fileOutputStream!=null){
try {
fileOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
4.缓冲流
BufferedInputStream/ BufferedOutputStream
//非文本文件的复制
//缓冲流作用:提高流的读取、写入操作 原因:内部提供了一个缓冲区
@Test
public void BufferedSteramTest(){
FileInputStream fileInputStream = null;
FileOutputStream fileOutputStream = null;
BufferedInputStream bufferedInputStream = null;
BufferedOutputStream bufferedOutputStream = null;
try {
//1.流文件
File srcfile = new File("QQ图片20211031203805.jpg");
File destFile = new File("QQ图片20211031203806.jpg");
//2.造流
//2.1 造节点流
fileInputStream = new FileInputStream(srcfile);
fileOutputStream = new FileOutputStream(destFile);
//2.2 造缓冲流
bufferedInputStream = new BufferedInputStream(fileInputStream);
bufferedOutputStream = new BufferedOutputStream(fileOutputStream);
//3.读取、写入
byte[] buffer = new byte[10];
int len;
while((len = bufferedInputStream.read(buffer)) != -1){
bufferedOutputStream.write(buffer,0,len);
}
} catch (IOException e) {
e.printStackTrace();
} finally {
//资源关闭
//要求:先关闭外层的流,在关闭内层的流
if(bufferedOutputStream != null){
try {
bufferedOutputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if(bufferedInputStream != null){
try {
bufferedInputStream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
//说明:再关闭外层流的时候,内层流也会关闭
// fileOutputStream.close();
// fileInputStream.close();
}
}
BufferedReader/ BufferedWriter
public class myTest {
@Test
public void testFileInputstream() {
BufferedReader bufferedReader = null;
BufferedWriter bufferedWriter = null;
try {
File file1 = new File("hello.txt");
File file2 = new File("hello2.txt");
FileReader reader = new FileReader(file1);
FileWriter writer = new FileWriter(file2);
bufferedReader = new BufferedReader(reader);
bufferedWriter = new BufferedWriter(writer);
char[] chaf = new char[5];
int len;
while ((len = bufferedReader.read(chaf))!=-1){
bufferedWriter.write(chaf, 0, len);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if(bufferedReader!= null){
try {
bufferedReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
if(bufferedWriter!= null){
try {
bufferedWriter.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
5.转换流
转换流:属于字符流 作用:提供字节流与字符流之间的转换
InputstreamReader:将一个字节的输入流转换为字符的输入流
OutputStreamlriter:将一个字符的输出流转换为字节的输出流
解码:字节、字节数组—>字符数组、字符串
编码:字符数组、字符串—>字节、字节数组
public class myTest {
@Test
public void test() {
InputStreamReader inputStreamReader = null;
try {
File file = new File("hello.txt");
FileInputStream inputStream = new FileInputStream(file);
//InputStreamReader inputStreamReader = new InputStreamReader(inputStream); 系统默认
inputStreamReader = new InputStreamReader(inputStream,"utf-8");
char[] cbuf = new char[5];
int len;
while ((len = inputStreamReader.read(cbuf))!=-1){
for (int i = 0; i <len ; i++) {
System.out.print(cbuf[i]);
}
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if(inputStreamReader!=null){
try {
inputStreamReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
6.输入、输出流
System.in:标准的输入流,默认从键盘输入
System.out:标准的输出流,默认从控制台输出
system类的setin( InputStream is) / setout(PrintStream ps)方式重新指定输入和输出的流。
练习:从键盘输入字符串,要求将读取到的整行字符串转成大写输出。然后继续进行输入操作,直至当输入“e”或者“exit”时,退出程序。
public class SystemInTest {
public static void main(String[] args) {
BufferedReader bufferedReader = null;
try {
InputStreamReader inputStreamReader = new InputStreamReader(System.in);
bufferedReader = new BufferedReader(inputStreamReader);
while (true){
System.out.println("请输入一个字符串:");
String line = bufferedReader.readLine();
if ("e".equalsIgnoreCase(line)||"exit".equalsIgnoreCase(line)){
System.out.println("退出程序");
break;
}
String s = line.toUpperCase();
System.out.println(s);
}
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (bufferedReader!=null){
try {
bufferedReader.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
7.打印流
打印流:PrintStream和Printwriter
提供了一系列重载的print()和println( )
8.数据流
DataInputStream 和DataoutputStream
作用:用于读取或写出基本数据类型的变量或字符串
public class MyTest {
@Test
public void test(){
DataOutputStream dataOutputStream = null;
try {
//练习:将内存中的字符串、基本数据类型的变量写出到文件中。
dataOutputStream = new DataOutputStream(new FileOutputStream("data.txt"));
dataOutputStream.writeUTF("快乐小子");
dataOutputStream.flush();
dataOutputStream.writeInt(20);
dataOutputStream.flush();
dataOutputStream.writeBoolean(true);
dataOutputStream.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if(dataOutputStream!=null){
try {
dataOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
//将文件中存储的基本数据类型变量和字符串读取到内存中,保存在变量中。
@Test
public void test2() {
DataInputStream dataInputStream = null;
try {
dataInputStream = new DataInputStream(new FileInputStream("data.txt"));
String utf = dataInputStream.readUTF();
int anInt = dataInputStream.readInt();
boolean aBoolean = dataInputStream.readBoolean();
//注意点:读取不同类型的数据的顺序要与当初写入文件时,保存的数据的顺序一致!
System.out.println(utf);
System.out.println(anInt);
System.out.println(aBoolean);
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if(dataInputStream!=null){
try {
dataInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
9.对象流
ObjectlnputStream和OjbectOutputSteam
用于存储和读取基本数据类型数据或对象的处理流。它的强大之处就是可以把Java中的对象写入到数据源中,也能把对象从数据源中还原回来。
- 序列化:用ObjectOutputStream类保存基木类型数据或对象的机制
- 反序列化:用ObjectInputStream类读取基本类型数据或对象的机制
ObjectOutputStream和1ObjectlnputStream不能序列化static和ltransient修饰的成员变量
对象序列化机制允许把内存中的Java对象转换成平台无关的二进制流,从而允许把这种二进制流持久地保存在磁盘上,或通过网络将这种二进制流传输到另一个网络节点。当其它程序获取了这种二进制流,就可以恢复成原来的Java对象
/*
Person需要满足如下的要求,方可序列化
1.需要实现接口: Serializable
2.当前类提供一个全局常量: serialVersionUID
除了当前Person类需要实现Serializable接口之外,还必须保证其内部所有属性也必须是可序列化的。
(默认情况下,基本数据类型可序列化)
*/
public class Person implements Serializable {
static final long serialVersionUID = 4216516565L;
private String name;
private int age;
private Accent accent;
public Person(String name, int age, Accent accent) {
this.name = name;
this.age = age;
this.accent = accent;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public Accent getAccent() {
return accent;
}
public void setAccent(Accent accent) {
this.accent = accent;
}
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public String toString() {
return "Person{" +
"name='" + name + '\'' +
", age=" + age +
", accent=" + accent +
'}';
}
}
class Accent implements Serializable{
static final long serialVersionUID = 4216516565L;
private int balance;
public Accent(int balance) {
this.balance = balance;
}
public int getBalance() {
return balance;
}
public void setBalance(int balance) {
this.balance = balance;
}
@Override
public String toString() {
return "Accent{" +
"balance=" + balance +
'}';
}
}
public class MyTest {
@Test
public void test(){
ObjectOutputStream objectOutputStream = null;
try {
//序列化:将内存中的java对象保存到磁盘或者通过网络传输出去
objectOutputStream = new ObjectOutputStream(new FileOutputStream("Object.det"));
objectOutputStream.writeObject(new String("快乐小子"));
//java.lang.RuntimeException: java.io.NotSerializableException:
objectOutputStream.writeObject(new Person("Tom", 20,new Accent(100)));
objectOutputStream.flush();
} catch (IOException e) {
throw new RuntimeException(e);
} finally {
if (objectOutputStream!=null){}{
try {
objectOutputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
@Test
public void test2(){
ObjectInputStream objectInputStream = null;
try {
//反序列化 将磁盘文件中的对象还原为内存中的一个java对象
objectInputStream = new ObjectInputStream(new FileInputStream("Object.det"));
;
Object o = objectInputStream.readObject();
String str = (String)o;
System.out.println(str);
Object o2 = objectInputStream.readObject();
Person o1 = (Person) o2;
System.out.println(o1);
} catch (IOException e) {
throw new RuntimeException(e);
} catch (ClassNotFoundException e) {
throw new RuntimeException(e);
} finally {
if (objectInputStream!=null){
try {
objectInputStream.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}
}
10.随机存取文件流
RandomAccessFile
RandomAccessFile声明在java.io包下,但直接继承于java.lang.Object类。并且它实现了Datalnput、DataOutput这两个接口,也就意味着这个类既可以读也可以写。
RandomAccessFile类支持“随机访问”的方式,程序可以直接跳到文件的任意地方来读、写文件
支持只访问文件的部分内容,可以向已存在的文件后追加内容
RandomAccessFile对象包含一个记录指针,用以标示当前读写处的位置。RandomAccessFile类对象可以自由移动记录指针:
long getFilePointer():获取文件记录指针的当前位置
void seek(long pls):将文件记录指针定位到pos位置
‘r’ 以只读方式打开。调用结果对象的任何 write 方法都将导致抛出 IOException。
“rw” 打开以便读取和写入。如果该文件尚不存在,则尝试创建该文件。
“rws” 打开以便读取和写入,对于 “rw”,还要求对文件的内容或元数据的每个更新都同步写入到底层存储设备。
“rwd” 打开以便读取和写入,对于 “rw”,还要求对文件内容的每个更新都同步写入到底层存储设备。
public class MyTest {
@Test
public void test() throws Exception {
//他会将原有文件进行覆盖
RandomAccessFile rwd = new RandomAccessFile("hello.txt", "rwd");
rwd.seek(5);//将指针调到5的位置
rwd.write("hello".getBytes());//hellohellod
rwd.close();
}
@Test
public void text2() throws Exception {
// 实现对文件内容的插入
RandomAccessFile rwd = new RandomAccessFile("hello.txt", "rwd");
rwd.seek(5);//将指针调到5的位置
//保存指针5后面的所有数据
StringBuffer buffer = new StringBuffer((int) new File("hello.txt").length());
byte[] bytes = new byte[5];
int len;
while ((len = rwd.read(bytes))!=-1){
buffer.append(new String(bytes, 0, len));
}
//调回指针
rwd.seek(5);//将指针调到5的位置
rwd.write("hello".getBytes());
rwd.write(buffer.toString().getBytes());
rwd.close();
}
}