字节流
InputStream
InputStream
是 Java 标准库提供的最基本的输入流,它位于java.io
包中,这个包提供了所有同步阻塞式 IO 的功能。
InputStream
并不是一个接口,而是一个抽象类,它是所有输入流的超类,这个抽象定义了一个最重要的方法就是int read()
。这个方法会读取输入流的下一个字节,并返回字节表示的int
值(0~255)。如果读到末尾,返回-1
表示不能再读取了。
基本使用
FileInputStream
是InputStream
的一个子类,它可以从文件中读取数据。
复制
上面的程序还存在一些问题,即在读取文件数据之前,我们须提前得到文件中的字符数量,如果字符比较多的情况下,就需要调用很多次read
方法。此时我们可以通过循环来去读文件中的字符。
复制
异常处理
在读取或写入 IO 流的过程中,可能会发生错误,这些错误由 Java 虚拟机自动封装成IOException
异常并抛出。因此,所有IO操作都必须正确处理IOException
异常。
复制
使用try...finally
来处理上述代码会比较复杂,更好的写法是利用 Java7 引入的try(resource)
语法,只需要编写try
语句,让编译器自动来关闭资源。
复制
实际上,编译器并不会特别地为InputStream
加上自动关闭。编译器只看try(resource = ...)
中的对象是否实现了java.lang.AutoCloseable
接口,如果实现了,就自动加上finally
语句并调用close()
方法。InputStream
和OutputStream
都实现了这个接口,因此,都可以用在try(resource)
中。
缓冲
在读取流资源的时候,一次一个字节的读取效率不高。很多流支持一次性读取多个字节到缓冲区,对于文件和网络流来说,利用缓冲区一次性读取多个字节效率往往要高很多。
复制
中文字符乱码
当文本文件中出现中文字符时,会出现中文乱码问题,这是因为在utf-8
字符编码下,一个中文字符占3个字节,所以按照字节读取时,容易把一个完整的文字劈开,所以会出现中文乱码问题。
无论是在 IO 的读取还是写入中,通过字节流来进行读写操作都会导致中文乱码的问题,要想解决问题,需要使用字符流Reader
和Writer
。
ByteArrayInputStream
用FileInputStream
可以从文件获取输入流,这是InputStream
最常用的一个实现类。此外ByteArrayInputStream
可以在内存中模拟一个InputStream
:
ByteArrayInputStream
实际上是把一个byte[]数组在内存中变成一个InputStream
,虽然实际应用不多,但是在测试的时候,可以用它来构造一个InputStream
。
因为在使用FileInputStream
时,就需要在本地磁盘中放一个真实的文本文件,而在测试的时候,往往没有这个文件,就可以用ByteArrayInputStream
来模拟一个InputStream
。
复制
Outputstream
基本使用
和InputStream
类似,OutputStream
也是抽象类,它是所有输出流的超类。OutputStream
最重要的一个方法就是void write(int b)
。
复制
这个方法会写入一个字节到输出流,虽然传入的是int
参数,但是只会写入一个字节,即int
最低8位表示字节的部分(相当于b & 0xff
)。
复制
OutputStream
提供了close
和flush
方法。
flush方法
为什么需要使用flush
方法?因为向磁盘、网络写入数据的时候,处于效率考虑,操作系统并不是输出一个字节就立即写入文件或发送网络,而是把输出的字节先放到内存的一个缓冲区(本质上是byte[]
)数组,等到缓冲区写满了,再一次性写入文件或网络。对于很多IO设备来说,一次写一个字节和1000个字节,花费的时间是一样的,所以OutputStream
有个flush()
方法,能强制把缓冲区内容输出。
通常情况下,我们不需要调用这个flush
方法,因为缓冲区写满了OutputStream
会自动调用它,并且在调用close
方法关闭之前,也会自动调用flush
方法。
手动调用flush
的案例
例如你正在开发一个应用程序,它需要记录重要事件和信息,以便后续分析和监控,这个应用程序需要在实时性方面非常敏感,因为事件的记录需要尽快写入日志文件,以便管理员能够及时查看并采取必要的措施。
在这种情况下,你会使用OutputStream
(通常是FileOutputStream
)来写入日志文件。为了确保日志信息尽快写入磁盘,你会手动调用flush()
方法,而不是等待缓冲区填满或等待自动刷新。这确保了日志事件的即时记录,即使应用程序在某个时间点崩溃,也可以确保已记录的事件不会丢失。
使用IO流进行文件拷贝
使用流进行文件拷贝使用缓冲进行文件拷贝
复制
最后更新于
这有帮助吗?