java将IO分为了两类
- -节点流:又称为"低级流"
特点:直接链接程序与另一端的"管道",是真实读写数据的流
IO一定是建立在节点流的基础上进行的。
文件流就是典型的节点流(低级流)
-- 处理流:又称为"高级流"
特点:不能独立存在,必须链接在其他流上
目的:当数据经过当前高级流时可以对数据进行某种加工操作,来简化我们的同等操作
实际开发中我们经常"串联"一组高级流最终到某个低级流上,使读写数据以流水线式的加工处理完成。这一操作也被称为使"流的链接"。
一.缓冲流
java.io.BufferedInputStream和BufferedOutputStream
1.功能
在流链接中的作用:**加快读写效率**
通常缓冲是最终链接在低级流上的流
2.构造器
- 缓冲字节输出流
BufferedOutputStream(OutputStream out)
实例化一个缓冲字节输出流并链接在指定的字节输出流上。默认缓冲区大小8kb(内部维护的byte[] buf数组长度8192)
BufferedOutputStream(OutputStream out,int size)
实例化一个指定缓冲区大小的缓冲字节输出流并链接在指定的字节输出流上。
- 缓冲字节输入流
BufferedInputStream(InputStream in)
实例化一个缓冲字节输入流并链接在指定的字节输入流上。默认缓冲区大小8kb(内部维护的byte[] buf数组长度8192)
BufferedInputStream(InputStream in,int size)
实例化一个指定缓冲区大小的缓冲字节输入流并链接在指定的字节输入流上。
原理
内部定义了一个属性byte[] buf。它等同于之前的块写操作。并且默认创建时,该buf数组的长度为8192(8kb)长度。缓冲流在读写数据时**总是以块读写数据**(默认是8kb)来保证读写效率的
**缓冲流提供了多种构造器,可以自行指定缓冲区大小。**
写缓冲问题
由于缓冲输出流会将写出的数据装满内部缓冲区(默认8kb的字节数组)后才会进行一次真实的写出操作。当我们的数据不足时,如果想要及时写出数据,可以调用缓冲流的flush()方法,强制将缓冲区中已经缓存的数据写出一次。
void flush()
强制将缓冲流的缓冲取(内部维护的字节数组)中已经缓存的字节一次性写出
flush的传递
flush()方法是被定义在java.io.Flushable中。而字节输出流的超类java.io.OutputStream实现了该接口,这意味着所有的字节输出流都有flush方法。而除了缓冲流之外的高级流的flush方法作用就是调用它链接的流的flush方法将该动作传递下去。最终传递给缓冲流来清空缓冲区。
二.对象流
java.io.ObjectInputStream和ObjectOutputStream
作用
-
对象输出流:将我们的java对象进行序列化
-
对象输入流:将java对象进行反序列化
序列化
将一个对象转换为一组可被传输或保存的字节。这组字节中除了包含对象本身的数据外,还会包含结构信息。
序列化的意义
实际开发中,我们通常会将对象
-
写入磁盘,进行长久保存
-
在网络间两台计算机中的java间进行传输
无论是保存在磁盘中还是传输,都需要将对象转换为字节后才可以进行。
对象输出流的序列化操作
void writeObject(Object obj) 将给定的对象转换为一组可保存或传输的字节然后通过其链接的流将字节写出
序列化对象时要求该对象对应的类必须实现接口:java.io.Serializable
如果写出的对象对应的类没有实现该接口,那么writeObject会抛出下面异常
NotSerializableException
对象输入流的序列化操作
java.io.ObjectInputStream使用对象流可以进行对象反序列化
构造器
ObjectInputStream(InputStream in)
将当前创建的对象输入流链接在指定的输入流上
方法
Object readObject()
进行对象反序列化并返回。该方法会从当前对象输入流链接的流中读取若干字节并将其还原为对象。这里要注意读取的字节必须是由ObjectOutputStream序列化一个对象所得到的字节。
返回值是Object,其他类型需要强制转换如
FileInputStream fis = new FileInputStream("person.obj");
ObjectInputStream ois = new ObjectInputStream(fis);Person person = (Person)ois.readObject();
transient关键字
当一个属性被transient关键字修饰后,该对象在进行序列化时,转换出来的字节中是不包含该属性的。忽略不必要的属性可以达到对象"瘦身"的操作。
对象瘦身可以在对象持久化时减少磁盘开销。在进行传输时可以缩短传输速度。
如果该对象不需要序列化,那么该关键字不发挥其他任何效果
序列化时不包含被transient属性,并且反序列化时该属性值为null
三.字符流
- java将流按照读写单位划分为字节流与字符流
- java.io.InputStream和OutputStream是所有字节流的超类
- java.io.Reader和Writer则是所有字符流的超类,它们和字节流的超类是平级关系.
- Reader和Writer是两个抽象类,里面规定了所有字符流都必须具备的读写字符的相关方法.
- 字符流最小读写单位为字符(char),但是底层实际还是读写字节,只是字符与字节的转换工作由字符流完成.
- 字符流都是高级流
常用方法
void write(int c) 写出一个字符,写出给定int值”低16”位表示的字符。
void write(char[] chs) 将给定字符数组中所有字符写出。
void write(String str) 将给定的字符串写出void write(char[] chs,int offset,int len):将给定的字符数组中从offset处开始连续的len个字符写出
int read():读取一个字符,返回的int值“低16”位有效。当返回值为-1时表达流读取到了末尾。
int read(char[] chs):从该流中读取一个字符数组的length个字符并存入该数组,返回值为实际读取到的字符量。当返回值为-1时表达流读取到了末尾。
四.转换流
java.io.InputStreamReader和OutputStreamWriter是常用的字符流的实现类。
实际开发中我们不会直接操作他们,但是他们在流连接中是必不可少的一环。
流连接中的作用
-
衔接字节流与其他字符流
-
将字符与字节相互转换
意义
实际开发中我们还有功能更好用的字符高级流.但是其他的字符高级流都有一个共通点:不能直接连接在字节流上.而实际操作设备的流都是低级流同时也都是字节流.因此不能直接在流连接中串联起来.转换流是一对可以连接在字节流上的字符流,其他的高级字符流可以连接在转换流上.在流连接中起到"转换器"的作用(负责字符与字节的实际转换)
构造器
OutputStreamWriter(OutputStream out,Charset cs)
基于给定的字节输出流以及字符编码创建OSW
OutputStreamWriter(OutputStream out)
该构造方法会根据系统默认字符集创建OSWInputStreamWriter(InputStream in,Charset cs)
基于给定的字节输入流以及字符编码创建当前转换流
InputStreamWriter(InputStream in)
该构造方法会根据系统默认字符集创建当前转换流
五.缓冲字符流
- 缓冲字符输出流-java.io.PrintWriter
特点:
-非缓冲:与 BufferedWriter 不同,PrintWriter 不使用内部缓冲区。这意味着一旦调用 print() 或 println() 方法,数据就会立即写入底层流。
-自动 flush:在默认情况下,PrintWriter 在遇到换行符 \n 时会自动刷新输出,确保内容立即可见。
-错误处理:如果在写入过程中发生错误,PrintWriter 可以设置为“检查错误状态”,在这种状态下,后续的写入操作会被忽略,直到调用 checkError() 方法清除错误状态。
-格式化输出:虽然没有像 printf() 那样的内置格式化方法,但可以通过组合使用字符串、变量和运算符来实现简单的格式化输出。
常用方法:
print(Object obj):打印对象的字符串表示形式。
println():打印一个换行符。
println(Object obj):打印对象的字符串表示形式后跟着一个换行符。
format(String format, Object... args):在 Java 6 及以后版本中可用,类似于 C 风格的 printf,用于格式化输出。
flush():强制清空输出缓冲区。
close():关闭输出流。
- java.io.BufferedWriter和BufferedReader
BufferedWriter缓冲字符输出流
作用:
提供了字符缓冲功能,用于字符输出流。
写入数据时,它会将数据暂存到内部的缓冲区,而不是立即写入底层的字符流(如 FileWriter)。
当缓冲区填满或者用户调用 flush() 方法时,数据才会被实际写入到目标位置。
常用方法:
write(char[] chars):写入字符数组。
newLine():写入一个行分隔符,具体取决于平台。
write(String str):写入字符串。
flush():强制将缓冲区的内容写入底层流。
close():关闭流并释放资源。
BufferedReader缓冲字符输入流
作用:
提供了字符缓冲功能,用于字符输入流。
从底层字符输入流(如 FileReader)读取数据时,它会一次性读取多个字符到缓冲区,然后根据需要从缓冲区中提供数据。
这降低了对磁盘或网络I/O的调用频率,从而提高性能。
常用方法:
readLine():从输入流中读取一行文本。
read() 和 read(char[] chars):读取单个字符或字符数组。
skip(long n):跳过指定数量的字符。
close():关闭流并释放资源
- 缓冲字符流内部也有一个缓冲区,读写文本数据以块读写形式加快效率.并且缓冲流有一个特别的功能:可以按行读写文本数据.缓冲流内部维护一个char数组,默认长度8192.以块读写方式读写字符数据保证效率
- java.io.PrintWriter具有自动行刷新的缓冲字符输出流,实际开发中更常用.它内部总是会自动连BufferedWriter作为块写加速使用
--------------------------------------------------------------------------------------