IO流总结
1.io流的分类:
输入流:读数据
输出流:写数据
数据类型分类
字节流
-
字节输入流
-
字节输出流
字符流:
-
字符输入流
-
字符输出流
使用场景:纯文本优先用字符流;操作图片、音频、视频等二进制文件用字节流;不确定就用字节流。
字节流抽象基类 -
InputStream:这个抽象类是表示字节输入流的所有类的超类
-
OutputStream:这个抽象类是表示字节输出流的所有类的超类
-
子类名特点:子类名称都是以其父类名作为子类名的后缀
字节输出流
FileOutputStream(String name):创建文件输出流以指定的名称写入文件
写数据的步骤:创建字节输出流对象—调用写数据方法—释放资源。
写数据的三种方式:
- void write(int b):字节写入,一次只能写一个。
- void write(byte[] b):把一个字节数组写入。
- void write(byte[] b, int off, int len):写入一个字节数组中从off索引开始的len个字节数据。
字节流写数据如何实现换行:
windows:\r\n;linux:\n;mac:\r;
跨平台回车换行符:String s = System.lineSeparator()。
字节流写数据如何实现追加写入
public FileOutputStream(String name,boolean append),如果第二个参数为true ,则字节将写入文件的末尾而不是开头
写数据加异常处理
try{
可能出现异常的代码;
}catch(异常类名 变量名){
异常的处理代码;
}finally{
执行所有清除操作;
}
finally下的语句一定会执行
字节流读数据(FileInputStream(String name)):
步骤:创建字节输入流对象---调用读数据方法---释放资源(一次只能读一个字节,想要多次读取需要使用循环)。
字节流复制文件(一次读写一个字节):
先用字节流读方法从源文件获取到每一个字节,然后写入到目标文件中。
一次读一个字节数组的方法:
public int read(byte[] b):从输入流读取最多b.length个字节的数据
数组拷贝原理分析
2.字节缓冲流
缓冲流特点:
能提高读写的效率,减少了内存和硬盘之间的IO操作次数。
字节缓冲流介绍:
-
BufferOutputStream:字节缓冲输出流
-
BufferedInputStream:字节缓冲输入流
每次从文件中读取8192个字节存到缓冲区,直到装满了再重新读取下一个8192字节;写数据也是先写入到缓冲区,缓冲区到了8192才会写入到文件中。 flush()方法:当文件最后读取不够8192个字节时,这个方法可以强制将缓冲区的字节写入到文件中(缓冲流关闭也会触发)。
缓冲流一次读写一个字节原理
字节缓冲流读写一个字节数组原理
使用数组的作用:通过数组减少二个缓存区之间在内存中拷贝的次数
3.字符流
使用字符流的原因: 使用字节流操作中文有可能出现乱码现象
编码表:字符和数值之间的映射表。
GBK:中英文都用2个字节表示,中文最高位为1.
UTF-8:英文用1个字节表示,中文用3个字节表示。
字符串中的编码解码方式:
- byte[] getBytes():字符串编码成字节数组,使用默认字符集。
- byte[] getBytes(String charsetName):使用只等字符集将字符串编码成字节数组。
- String(byte[] bytes) :使用默认字符集将字节数组解码成字符串。
- String(byte[] bytes, String charsetName):使用指定字符集把字节数组解码成字符串。
字节流读取中文原理:
字符流 = 字节流 + 编码表
因为中文在任意码表中的第一个字节都是负数,所以可以根据负数字节开始编码成中文(GBK是2个字节,UTF-8是3个字节)。
字符流读写数据
介绍:
写数据:
- Writer: 用于写入字符流的抽象父类
- FileWriter: 用于写入字符流的常用子类
读数据: - Reader: 用于读取字符流的抽象父类
- FileReader: 用于读取字符流的常用子类
读写数据构造方法与成员方法
写数据:
读数据:
字符流写入注意事项:
- 文件不存在时,会自动进行创建 前提是文件夹必须存在
- 写入数字,实际写入的是该数字对应码表上的字符
- 资源释放
flush和close方法
- flush() 刷新流,之后还可以继续写数据
close() 关闭流,释放资源,但是在关闭之前会先刷新流。一旦关闭,就不能再写数据
4.字符缓冲流
字符缓冲流介绍
- BufferedWriter:字符缓冲输出流,缓冲区大小默认8192个字符
- BufferedReader:字符缓冲输入流,缓冲区大小默认8192个字符
构造方法
字符缓冲流特有功能
BufferedWriter:
void newLine() 写一行行分隔符,行分隔符字符串由系统属性定义
BufferedReader:
String readLine() 读一行文字。 结果包含行的内容的字符串,不包括任何行终止字符如果流的结尾已经到达,则为null
IO流总结
5.转换流
字符流中和编码解码
- InputStreamReader:是从字节流到字符流的桥梁,父类是Reader
读取字节并使用指定编码将其解码为字符
字符集可以是名称指定,或是明确指定,或默认字符集 - OutputStreamWriter:是从字符流到字节流的桥梁,父类是Writer
从字符流到字节流的桥梁,用指定编码将写入的字符编码为字节
字符集可以是名称指定,或是明确指定,或默认字符集
转换流写数据
6.对象操作流
对象序列化流
介绍:
- 对象序列化:就是将对象保存到磁盘中,或者在网络中传输对象
- 这种机制就是使用一个字节序列表示一个对象,该字节序列包含:对象的类型、对象的数据和对象中存储的属性等信息
- 字节序列写到文件之后,相当于文件中持久保存了一个对象的信息
- 反之,该字节序列还可以从文件中读取回来,重构对象,对它进行反序列化
- 对象序列化流: ObjectOutputStream
构造方法与序列化对象方法
对象反序列化流
介绍:
对象反序列化流: ObjectInputStream
- ObjectInputStream反序列化先前使用ObjectOutputStream编写的原始数据和对象
构造方法与序列化对象方法
serialVersionUID & transient
- serialVersionUID
表示序列号,我们在定义类的时候如果不定义,系统会帮我们定义一个,但每次修改类的信息时,该序列号会发生改变。 - 对象序列化之后,如果修改了类信息,然后再读取数据是否会出问题,出什么问题?
回出问题,会抛出InvalidClassException异常 - 上述问题如何解决?
给对象所属的类加一个serialVersionUID,我们自己指定一个值,这样序列号在读写过程中就不会发生改变了。 - 在idea中如何来定义一个serialVersionUID?
7.Properties集合
Properties介绍
- 是一个Map体系的集合类
- Properties可以保存到流中或从流中加载
- 属性列表中的每个键及其对应的值都是一个字符串
Properties特有方法
- Object setProperty(String key, String value) 设置集合的键和值,都是String类型,底层调用
Hashtable方法 put String getProperty(String key) 使用此属性列表中指定的键搜索属性
Set stringPropertyNames() 从该属性列表中返回一个不可修改的键集,其中键及其对应的值是字符串
Properties和IO流相结合的方法
- void load(Reader reader) 从输入字符流读取属性列表(键和元素对)
- void store(Writer writer, String comments) 将此属性列表(键和元素对)写入此 Properties表中,以适合使用 load(Reader)方法的格式写入输出字符流