1、I/O输入输出,所有的IO都被视作是单个字节的移动,通过stream对象一次移动一个字节。流IO负责把对象转换为字节,然后再转换为对象。
NIO提供了二套NIO,一套是针对标准输入输出NIO,另一套是网络编程NIO
2、流与块的比较
NIO和IO最大的区别是数据打包和传输方式,IO是以流的方式来处理数据,而NIO是以块的方式处理数据。 面向块的IO系统以块的形式处理数据,
每一个操作都在一步中产生或消费一个数据块。按块要比按流快的多
3、NIO基础
buffer和channel是标准NIO中核心对象(网络NIO还有一个Selector核心对象)channel是对原io中流的模拟,任何来源和目的数据都必须通过一个channel对象,
一个buffer实质上是一个容器对象,发给channel的所有对象都必须先放到buffer中,同样的,从channel中读取的任何数据都要读到buffer中
3.1 buffer
buffer是一个对象,包含一些要写入或读出的数据。在NIO中,数据是放入buffer对象的,而在IO中,数据是直接写入或者读到stream对象的。应用程序不能直接对channel进行读写操作,而必须通过buffer来进行,即channel是通过buffer来读写数据的。 在NIO中,所有的数据都是用buffer处理的,是NIO读写数据的中转池。buffer实质上是一个数组,通常是一个字节数据,但也可以是其他类型的数组但一个缓冲区不仅仅是一个数组,重要的是它提供了对数据的结构化访问,而且还可以
跟踪系统的读写进程
buffer: 读写数据一般四个步骤:
1)写入数据到buffer
2) 调用flip方法
3)从buffer中读取数据
4)调用clear方法或者compact方法
当向buffer写入数据时,buffer会记录下写了多少数据。一旦要读取数据,需要通过flip方法将buffer从写模式切换到读模式。在读模式下,可以读取之前写入到buffer的所有数 据。一旦读完了所有的数据,就需要情况缓冲区,让它可以再次被写入。有二种方式能清空缓冲区clear或compact方法。clear会清空整个缓冲区,compact知会清除已经读过得数据。任何未读的数据都被移到缓冲区的起始处,新写入的数据将放到缓冲区未读数据的后面
3.2 channel,可以通过它读取和写入数据。
1)channel是双向的,既可以读也可以写,而流是单向的
2) channel可以进行异步的读写
3) 对channel的读写必须通过buffer对象
在NIO中channel主要有如下几种类型:
1)FileChannel:从文件读取数据
2) DatagramChnanel : 读写UDP忘了协议数据
3) SocketChannel : 读写TCP忘了协议数据
4) ServerSocketChannel : 可以监听tcp连接
NIO中读和写:
4.1 从文件中读取
1)从FileInputStream读取channel
2)创建buffer
3)从channel读取数据到buffer
FileInputStream fin = new FileInputStream("readme.txt");
FileChannel channel = fin.getChannel();
//创建缓冲区
ByteBuffer buffer = ByteBuffer.allocate(1024);
channel.read(buffer);
4.2 写入数据到文件
FileOutputStream fos = new FileOutputStream("out.txt");
FileChannel channel = foc.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
for(int i=0; i < message.length; ++i){
buffer.put(message[i]);
}
channel.write(buffer);
4.3 读写结合demo
创建一个buffer 然后从源文件读取数据到缓冲区,然后再从缓冲区写入目标文件
public static void copyFileUseNIO(String src, String dst) throws Exception{
FileInputStream fis = new FileInputStream(new File(src));
FileOutputStream fos = new FileOutputStream(new File(dst));
FileChannel inchannel = fis.getChannel();
FileChannel outChannel = fos.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
while(true){
int eof = inchannel.read(buffer);
if(eof == -1) {
break;
}
//重设一下buffer的position=0,limit=position
buffer.flip();
outchannel.write(buffer);
//写完要重置buffer,重设position=0,limit=capacity
buffer.clear();
}
finChannel.close();
fosChanenl.close();
fis.close();
fos.close();
}