JAVA IO

发布时间:2024年01月13日

??流是一个抽象的概念,代表了数据的无结构化传递。流的本质是数据在不同设备之间的传递。在Java中,数据的读取和写入都是以流的方式进行的。
??在Java中,根据数据流向的不同,可以将流分为输入流和输出流;根据单位的不同,可以将流分为字节流和字符流;根据等级的不同,可以将流分为节点流和处理流。

1.输入流和输出流

输入流:输入流用于将数据从控制台、文件、网络等外部设备输入应用程序进程中
输出流:输出流用于将应用程序进程中的数据输出到控制台、文件、显示器等中。

2.字节流和字符流

(1)字节流:字节流以字节(8个bit)为单位对数据进行读写操作,因此主要用于处理二进制数据。在Java中使用InputStream和OutputStream处理字节数据。抽象类InputStream和OutputStream构成了输入/输出(IO)类层次结构的基础。
??如果想要读写字符串和数字,就需要功能更加强大的子类,例如DataInputStream和DataOutputStream可以以二进制格式读写所有的基本Java类型,ZipInputStream和ZipOutputStream可以以常见的ZIP压缩格式读写文件。
(2)字符流:字符流以字符为单位对数据进行读写操作,一次读取或写入都是以16bit为单位进行的。Java中的字符采用Unicode编码,一个字符占用2字节。字符流主要用于处理文本数据的读写,在处理过程中需要进行字符集的转换。在Java中使用Reader、Writer处理字符数据。
close()、flush()
??当你完成对流的读写时,应该通过调用close方法来关闭它,这个调用会释放掉十分有限的操作系统资源。如果一个应用程序打开了过多的流而没有关闭,那么系统资源将被耗尽。关闭一个输出流的同时还会冲刷用于该输出流的缓冲区:所有被临时置于缓冲区中,以使用更大的包的形式传递的字符在关闭输出流时都将被送出。特别是,如果不关闭文件,那么写出字节的最后一个包可能将永远得不到传递。当然,我们还可以用flush方法来人为地冲刷这些输出。
一般只有数据量特别大的时候才需要在中间的时候就flush(),否则一般只需要close()就可以了

字节流和字符流的基本方法类似,都含有read(),write(),close(),输出流都有flush()
对于文本输出,推荐使用PrintWriter,这个类拥有以文本格式打印字符串和数字的方法,它的输出功能强大。与字节流类似,字符流也可以包装BufferedWriter提高访问数据的效率。但是由于字节流本身没有缓冲区,故缓冲字节流相较于字节流,效率提升就比较大;而字符流本身是有缓冲区的,所以说缓冲字符流对于字符流的效率提升就不是很大。

3.节点流和处理流

??节点流是低级流,直接与数据源相接,对数据源上的流进行读写。
??处理流是高级流,采用修饰器模式对节点流进行了封装,不直接与数据源相连,主要用于消除不同节点流的实现差异,提供更方便的方法来完成数据的输入和输出。
??例如,FileInputStream、FileOutputStream、FileReader、FileWriter属于节点流;BufferInputStream、BufferOutputStream、BufferReader、BufferWriter属于处理流。

相对于节点流,处理流有如下特性:

  • 性能高:处理流通过增加缓存的方式提高数据的输入和输出效率。
  • 操作方便:处理流封装了一系列高级方法来完成一次性大批量数据的输入和输出。

比如,节点流 FileInputStream和FileOutputStream只支持在字节级别上的读写,没有任何读入和写入数值类型的方法;与之相反,处理流中的DataInputStream和DataOutputStream没有任何从文件中获取数据或写入数据的方法。Java程序员需要对二者进行组合,例如实现从文件中读入数字,具体代码如下:

FileInputStream fin = new FileInputStream("emplyee.dat");
DataInputStream din = new DataInputStream(fin);
double s = din.readDouble();

??处理流又称过滤流,是对已存在的节点流或其他处理流的进一步处理。FilterInputStream和FilterOutputStream及其子类都都是处理流,可以向原生的字节流添加额外的功能。我们可以通过嵌套过滤器来添加多重功能。

DataInputStream din = new DataInputStream(new BuffedInputStream(new FileInputStream("employ.dat")));

上面的代码就产生了一个可读取数据的带缓冲机制的输入流,带有缓冲机制可以使的数据的获取更加高效。

4.内存映射文件技术

操作系统可以利用虚拟内存实现将一个文件或者文件的一部分“映射”到内存中。然后这个文件就可被都当作内存数据来访问,比传统的文件要快得多,这种技术就是内存映射文件技术。
Java中的nio包支持内存映射文件技术,在Java中将一个文件映射到内存并操作共分为如下3步:
(1)从文件中获得一个通道
(2)调用FileChannel的map方法将文件映射到虚拟内存
可以通过mode参数指定映射模式。
(3)调用MappedByteBuffer的put(byte[] src)向内存映射文件中写入数据,调用get(int index)获取文件中对应索引的数据,以字节形式返回。

相关问题

(1)字节流可以处理Unicode字符吗?
??字节流在处理数据时,是以字节为单位进行读写的。对于Unicode字符,一个字符可能由一个或多个字节组成,具体取决于所使用的字符编码。如果直接使用字节流处理Unicode字符,可能会导致字符编码不一致,从而出现乱码或错误解释的情况。
??字符流(Reader和Writer)在设计上更适合处理字符数据,它们能够理解并正确处理字符编码,提供了更高层次的抽象,使得处理Unicode字符更为方便和安全。
??因此,虽然字节流理论上可以处理Unicode字符,但为了确保正确处理字符编码、避免乱码和数据错误解释,更推荐使用字符流进行Unicode字符的读写操作。

(2)字节流与字符流的区别

  • 读写单位不同:字节流以字节为单位进行读写,字符流以字符为单位进行读写。
  • 处理对象不同:由于字节流可以处理任何类型的数据,所以它常常用于处理二进制数据,如图片,音频,视频等。而字符流由于可以自动处理字符编码,所以它更适合处理文本数据。
  • 缓冲区要求不同:字节流在处理输入和输出时,直接与底层操作系统交互,数据不经过任何处理直接读写。而字符流在处理输入和输出时,会对数据进行缓冲,即数据会被存储在内部缓冲区中,当缓冲区满时才会进行物理磁盘操作。
    补充:由于字节流本身没有缓冲区,故缓冲字节流相较于字节流,效率提升就比较大;而字符流本身是有缓冲区的,所以说缓冲字符流对于字符流的效率提升就不是很大。
  • 编码处理:字节流在读取或写入数据时,不会处理任何字符编码(如UTF-8,GBK等),它们只是简单地读取或写入二进制数据。而字符流在读取或写入数据时,会自动处理字符编码和解码。

本篇博客参考了王磊的<<Offer来了>>第二版

文章来源:https://blog.csdn.net/weixin_44145526/article/details/135567599
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。