Java NIO 入门(三)从理论到实践:使用NIO读写
程序员文章站
2022-07-13 17:01:24
...
Java NIO 入门(三)从理论到实践:使用NIO读写
guibin.beijing@gmail.com
概述
读和写是最基础的IO处理。从Channel中读是非常简单的,我们只要创建一个Buffer,然后要求Channel往Buffer中读数据。写也很简单,也需要创建一个Buffer,把要写的数据填充到Buffer中,然后要求Channel把Buffer中的数据写出去。
在这节中,我们学习使用JAVA程序来读写数据,顺便浏览一下NIO的主要组件(Buffer,Channel以及相关的方法)并且看看他们在读写数据时如何交互,在后面的章节中我们将依次查看每个组件的细节。
从文件中读数据
在第一个练习中,我们首先从文件中读取一些数据。如果使用老的IO,只需要简单的创建FileInputStream,然后从中读取数据。在NIO中,事情变得有些不同了,首先需要从FileInputStream中获取Channel对象,然后使用这个Channel去读文件。
在NIO系统中任何时刻执行一个读操作时,都要从Channel中读,但不是直接从Channel中读。由于所有的数据都需要通过Buffer承载,所以需首先从Channel中把数据读进Buffer。
因此,从文件中读数据一共有三步:
下面我们仔细看看具体时如何工作的。
三步简单的工作
第一步获取Channel。从FileInputStream中获取Channel。
第二步创建Buffer
最后一步,将文件内容通过Channel读入Buffer中
你一定发现,在这里,并没有告诉Channel把多少内容读进Buffer。在每个Buffer中都有一套完整的内部计数系统来跟踪已经读了多少数据了,Buffer中还剩多少空间。关于Buffer的计数系统在随后的“Buffer内部原理”中讲解。
写文件
使用NIO写文件和读文件非常类似。我们还是从FileOutputStream中获取Channel。
下一步还是创建Buffer并且把数据放到Buffer中。在这种情况下数据将从一个叫做message的数组中取出,这个数组中包含了字符串ASCII码的字节。(The buffer.flip() 和 buffer.put()在后面讲解)
最后一步就是把Buffer写出去。
再次注意,我们没有必要告诉Channel总共要写多少数据,Buffer的内部计数系统会跟踪已经写了多少数据了,还剩多少空间可以使用。
边读边写
下面看看当我们把读和写结合起来会发生什么。这个练习程序的名称叫CopyFile.java,用来从一个文件拷贝全部数据到另一个文件。Copy.java包含了三个基本的操作:
程序重复的进行读写、读写,直到文件读完。
CopyFile程序能够看到如何检查程序的状态,以及如何使用clear(),flip()方法重置Buffer,如何读数据从一个Channel到另一个Channel。
运行CopyFile例子
因为Buffer跟踪了自己的内部数据,因此CopyFile程序的内部循环非常简单,如下:
首先数据从输入Channel中读入Buffer,然后把数据写出到输出Channel中。因为输入和输出分别对应于两个文件,因此是两个Channel。
检查读文件的状态
下一步,当我们在拷贝时需要检查读文件的状态。当没有数据可读时即执行完毕,这个状态可以通过read()方法返回-1来判断,如下:
重置Buffer
最后,在从Channel将数据读入Buffer前调用clear()方法,相似的,在将Buffer写入输出Channel之前调用flip()方法。
clear()方法重置了Buffer,使其准备好能够将读入的数据放入Buffer中。flip()方法使得Buffer准备好把Buffer中的数据写入Channel。
本文参考自http://www.cs.brown.edu/courses/cs161/papers/j-nio-ltr.pdf
guibin.beijing@gmail.com
概述
读和写是最基础的IO处理。从Channel中读是非常简单的,我们只要创建一个Buffer,然后要求Channel往Buffer中读数据。写也很简单,也需要创建一个Buffer,把要写的数据填充到Buffer中,然后要求Channel把Buffer中的数据写出去。
在这节中,我们学习使用JAVA程序来读写数据,顺便浏览一下NIO的主要组件(Buffer,Channel以及相关的方法)并且看看他们在读写数据时如何交互,在后面的章节中我们将依次查看每个组件的细节。
从文件中读数据
在第一个练习中,我们首先从文件中读取一些数据。如果使用老的IO,只需要简单的创建FileInputStream,然后从中读取数据。在NIO中,事情变得有些不同了,首先需要从FileInputStream中获取Channel对象,然后使用这个Channel去读文件。
在NIO系统中任何时刻执行一个读操作时,都要从Channel中读,但不是直接从Channel中读。由于所有的数据都需要通过Buffer承载,所以需首先从Channel中把数据读进Buffer。
因此,从文件中读数据一共有三步:
- 从FileInputStream中获取Channel
- 创建Buffer
- 从Channel中把数据读入Buffer
下面我们仔细看看具体时如何工作的。
三步简单的工作
第一步获取Channel。从FileInputStream中获取Channel。
FileInputStream fin = new FileInputStream( "readandshow.txt" ); FileChannel fc = fin.getChannel();
第二步创建Buffer
ByteBuffer buffer = ByteBuffer.allocate( 1024 );
最后一步,将文件内容通过Channel读入Buffer中
fc.read( buffer );
你一定发现,在这里,并没有告诉Channel把多少内容读进Buffer。在每个Buffer中都有一套完整的内部计数系统来跟踪已经读了多少数据了,Buffer中还剩多少空间。关于Buffer的计数系统在随后的“Buffer内部原理”中讲解。
写文件
使用NIO写文件和读文件非常类似。我们还是从FileOutputStream中获取Channel。
FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" ); FileChannel fc = fout.getChannel();
下一步还是创建Buffer并且把数据放到Buffer中。在这种情况下数据将从一个叫做message的数组中取出,这个数组中包含了字符串ASCII码的字节。(The buffer.flip() 和 buffer.put()在后面讲解)
ByteBuffer buffer = ByteBuffer.allocate( 1024 ); for (int i=0; i<message.length; ++i) { buffer.put( message[i] ); } buffer.flip();
最后一步就是把Buffer写出去。
fc.write( buffer );
再次注意,我们没有必要告诉Channel总共要写多少数据,Buffer的内部计数系统会跟踪已经写了多少数据了,还剩多少空间可以使用。
边读边写
下面看看当我们把读和写结合起来会发生什么。这个练习程序的名称叫CopyFile.java,用来从一个文件拷贝全部数据到另一个文件。Copy.java包含了三个基本的操作:
- 首先创建Buffer
- 然后从源文件把数据读入Buffer
- 最后把Buffer写入目的文件
程序重复的进行读写、读写,直到文件读完。
CopyFile程序能够看到如何检查程序的状态,以及如何使用clear(),flip()方法重置Buffer,如何读数据从一个Channel到另一个Channel。
运行CopyFile例子
因为Buffer跟踪了自己的内部数据,因此CopyFile程序的内部循环非常简单,如下:
fcin.read( buffer ); fcout.write( buffer );
首先数据从输入Channel中读入Buffer,然后把数据写出到输出Channel中。因为输入和输出分别对应于两个文件,因此是两个Channel。
检查读文件的状态
下一步,当我们在拷贝时需要检查读文件的状态。当没有数据可读时即执行完毕,这个状态可以通过read()方法返回-1来判断,如下:
int r = fcin.read( buffer ); if (r==-1) { break; }
重置Buffer
最后,在从Channel将数据读入Buffer前调用clear()方法,相似的,在将Buffer写入输出Channel之前调用flip()方法。
buffer.clear(); int r = fcin.read( buffer ); if (r==-1) { break; } buffer.flip(); fcout.write( buffer );
clear()方法重置了Buffer,使其准备好能够将读入的数据放入Buffer中。flip()方法使得Buffer准备好把Buffer中的数据写入Channel。
本文参考自http://www.cs.brown.edu/courses/cs161/papers/j-nio-ltr.pdf
上一篇: 3种下载文件程序的思考,为何使用NIO进行异步网络通讯
下一篇: Java之nio学习