一、IO流
1、IO流:用来操作文件的数据。
2、IO流的分类:
1)按照操作数据的类型分为两种:字节流和字符流。
A、字节流:读取的是文件的二进制数据,不会对二进制做处理。不会解析成看得懂的数据。
B、字符流:读取的也是二进制数据,他会将二进制数据转换为我们能够识别的字符(解码)。字符流是字符为单位的。
C、字符流 = 字节流 + 解码。(可以认为)
2)流按照流的方向分:输入流和输出流。
A、判断是输入流还是输出流:以当前应用程序为参考,观察数据是流入还是流出,如果是流入就是输入流,流出则是输出流。
二、字节流:
1、字节输入流:
A、InputStream:此抽象类是表示字节输入流的所有类的超类,是抽象的类
2、如何判断一个流是字节输入流:
A、判断一下他的类名是否以InputStream结尾。
3、FileInputStream:是InputStream的子类
A、FileInputStream使用的步骤:4步
1)找到目标文件。 //NotFoundFileException :file路径可能有问题
File file = new File(“C:\\test.txt”);
2)建立通道
FileInputStream fileInputStream = new FileInputStream(file);
3)读取文件中的数据 read();//只获取一个字节
Int date = fileInputStream.read(); //需要抛异常
4)关闭资源(释放资源) //先开后关,后开先关
fileInputStream .close();
B、用循环来读取字节 //效率不高
方式一:
for(int i = 0; i < file.length(); i++) {
Int date = fileInputStream.read();
char c = (char)date;
}
方式二:
int content = 0;
While((content = fileInputStream.read()) != -1) {
System.out.print((char)content);
}
C、创建缓冲区来读取数据 //缺陷是不能读取一个完整的文件
3)创建一个缓冲区
byte[] b = new byte[(int)file.length()];
4)读数据
//缓冲区来读取数据:数据存在缓冲区字节数组里面
int count = fileInputStream.read(); //返回值就是文件的大小
System.out.pruntln(new String(b)); //帮我们解码了 直接输出字符串
new String(b, 0, count); //转化用这种好
D、(方式四)通过创建缓冲区和循环方式来读取
3)创建一个缓冲区
byte[] b = new byte[1024]; //一般用1024的倍数0
4)读取数据
int count = 0;
while((count = fileInputStream.read(b)) != -1) {
System.out.pruntln(new String(b, 0, count));
}
三、字节输出流:
1、OutPutStream: 他也是所有字节输出流的超类,也是一个抽象类,使用子类
2、FileOutPutStream 文件输出流
3、FileOutPutStream的使用步骤:
A、方式一:
1)找到目标文件
File file = new File(“D:\\a.txt”);
2)创建一个通道
FileOutputStream outputStream = new FileOutputStream();
3)开始写入数据
int a = 97;
outputStream.write(a); //每次输入一个字节
4)关闭资源
outputStream.close();
B、方式二:
3)创建一个字节数组
String str = “hello world”;
byte[] b = str.getBytes(); //将字符串变为字节数组
4)写入数据
outputStream.write(b);
4、FileOutputStream:的使用注意事项:
1)使用FileOutputStream写数据的时候,如果目标文件不存在,就会创建一个目标文件(在创建通道的时候创建文件
2)使用FileOutputStream写数据的时候,如果目标文件存在,先将里面的数据清空,再来写入数据。
3)使用FileOutputStream写数据的时候,如果目标文件存在,想将数据在原有的基础上追加,这个时候应该使用FileOutputStream(File file, boolean append);的构造方法,append为true就可以。
4)使用FileOutputStream写数据的时候,用write(int a); 方法写入数据,虽然接受的是int,但实际上只有一个字节的数据,操作的是低八位的二进制,其他的24位全部丢掉。
四、流的异常处理:
1、找到目标文件
2、建立通道 //处理异常
FileInputStream fileInputStream = nll;
try{
fileInputStream = new FileInputStream(file);
}catch{
//提示用户有错误要修改,让后面的代码停止运行
throw new RuntimeException(e);
} finally {
fileInputStream .close();
}
//注意:无论你使用的是输入流还是输出流,操作的一定是文件。
五、封装的输入流类
1、输入流中可以通过设置缓冲区来加大读取的效率。
2、Buffer来头的类:所有的缓冲流都是以Buffer开头的。
3、BufferInputStream:缓冲输入字节流,目的:提高读取文件的效率。
4、注意:BufferInputStream是没有读写数据的功能的。
5、内部实现:里面维护了一个8字节的byte数组。
6、BufferInputStream的使用步骤:
1)找到目标文件
File file = new File(“C:\\a.txt”);
2)创建通道
FileInputStream inputStream = new FileInputStream(file);
3)创建一个缓冲输入字节流
BufferedInputStream bufferedInputStream = new BufferedInputStream (inputStream);
4)开始写入数据
Int content = 0; //一次只会去一个字节
While((content = bufferedInputStream.read() != -1) {
System.out.println((char)content);
}
5)关闭通道
inputStream.close(); //也可以用bufferedInputStream.close();
六、缓冲字节输出流
1、BufferedOutStream:缓冲字节输出流
2、作用:提高文件的输出效率,还提供了一些其他方法。
3、注意:内部也维护了一个8KB的数组。
4、使用步骤:
1)找到目标文件
2)创建通道
FileOutputStream outputStream = new FileOutputStream(file);
3)创建缓冲字节输出流
BufferedOutputStream bufferedOutputStream = new BufferedOutputStream(outputStream);
4)创建写入文件的数据
String string = “today weather is good”;
5)写数据 //不会写入磁盘中 //除非数组中的数据满了,就会自动写入磁盘中
bufferedOutputStream.write(string.getBytes()); //这里只是将数据保存到内存中
//因为内部维护了一个8KB的数组
6)将数据写入到磁盘中
bufferedOutputStream.flush(); //刷新
7)关闭资源
bufferedOutputStream.close(); //关闭时会调用flush(); 内部实现
七、输入字符流
1、一个汉字占两个字节,字节流用的是read()一次制度取一个字节
2、new String(Byte[] b); //里面会解码
3、字符流:读的也是二进制文件,他会帮我们解码成我们看得懂的字符。
4、字符流 = 字节流 + 解码
5、字符输入流的根类:Reader 也是抽象的
1)FileReader :文件字符输入流
A、三种输入流 FileInputStream BufferedInputStream Reader
B、以InputStream或者Reader结尾的都是输入流
2)FileReader 的使用步骤:
方式一:
A、找目标文件
B、建立通道
FileReader fileReader = new FileReader(file);
C、读取数据
int content = 0; ///读取单个字符
While((content = fileReader.read()) != -1) {
打印(char)content
}
D、关闭资源
fileReader.close();
3)方式二:
C、建立一个缓冲区 字符数组
char[] c = new char[1024];
int length =0;
D、读取数据
While((length = fileReader.read(c)) != -1) {
System.out.println(new String(c, 0, length));
}
八、字符输出流:
1、Writer :字符输出流的根类,抽象的类
2、FileWriter 文件数据的输出字符流
3、Writer的使用步骤:
1)找到目标文件
File file = new File(“D:\\a.txt”);
2)建立通道
FileWriter fileWriter = new FileWriter(file , true); //在文件后面继续追加数据
3)写入数据
fileWriter.writer(“你好你好”);
4)关闭数据
fileWriter.close();
4、字符输出流的使用注意点:
1)FileReader内部维护了一个1024个字符的数组,所以在写入数据的时候,他是现将数据写入到内部的字符数组中,如果需要将数据写入到硬盘中,需要用到flush()或者关闭字符数组数据存满了。
2)向文件追加数据,需要使用new FileWriter(File, boolean)构造方法,参数为true
3)如果问文件不存在,就new一个
5、字符流解码:取系统默认的方式来解码 GBK
6、图片解码失败的原因是:图片中的二进制数据和GBK码表中的值进行对比,二进制文件中会有和码表中对应不上的数据,就会舍去,数据就损失了。
7、使用字节流的场景:读取的数据不需要转化为我们能看懂的字符时,如图片、视频、、
8、使用字符流场景:读写的数据需要转化为字符时。
九、字符缓冲输入流
字符缓冲流:缓冲流不具备读写数据的能力,但是可以提高读取数据的效率,可以扩展功能。内部维护了一个字符数组。
1、BufferedRead 缓冲字符输入流。
使用步骤:
1)创建通道并且指定路径
FileReader reader = new FileReader(“D:\\a.txt”);
2)创建缓冲流
BufferedReader bufferedReader = new BufferedReader (reader);
3)开始读取数据
Int content = 0;
While((content = bufferedReader.read() ) != -1) {
(char)content
}
4)关闭资源
bufferedReader.close();
2、有一个扩展功能:一次可以读取一行
String str = bufferedReader.readLine(); //读取一行
3、循环一行行取
String str = null;
Whiile((str = bufferedReader .readLine()) != null) {
}
十、字符缓冲输出流:BufferedWriter
1、内部提供一个8192长度的字符数组作为一个缓冲区。
2、BufferedWriter作用:提高写入的效率,拓展FileWriter的功能
3、使用步骤:
1)建立一个通道,指定路径
FileWriter writer = new FileWriter(“D:\\a.txt”);
2)创建缓冲流
BufferedWriter bufferedWriter = new BufferedWriter(writer);
3)开始写入数据
//bufferedWriter.newLine(); 让数据换行显示
bufferedWriter.writer(“数据数据”);
4)关闭资源
bufferedWriter.close(); //关闭资源之前会有刷新操作 调用 flush()
十一、对象流 将java中的对象写入磁盘中
1、OnjectInputStream :对象输入流
2、ObjectOutPutStream :对象输出流
3、对象的输入输出流的作用:用于写入对象的信息读取对象的信息。对象的持久化。 如:用户信息。
4、对象输出流的使用步骤:
1)指定目标文件
File file = new File(“D:\\person.txt”);
2)建立通道
FileOutputStream fileOutputStream = new FileOutputStream(file);
3)创建一个对象输出流
ObjectOutputStream objeOutPut = new ObjectOutputStream(fileOutputStream );
4)创建一个对象
Person p = new Person(“张三”, 20, 1001);
5)写数据
objeOutPut.writeObject(p);
6)关闭资源
5、使用注意点:
1)如果想将一个对象写入磁盘中,那么对象所属的类必须进行序列化,即实现接口:Serializable 它没有任何方法,只是一个标记接口
2)如果对象所属的类的成员变量发生改变,你在读取原来的对象就会报错,你只要保证serialVersionUID 唯一就可以了。设置为常量。
3)如果你不想将某些信息存入到磁盘,可以通过transient关键字修饰成员变量。
4)如果一个类中引用了另外的一个类,那么另外的这个类也要实现Serializable接口。