西安网站建设那家强,桂林北站有核酸检测点吗,网站动态与静态,网站建设方案怎么做一、基本概念 1、I/0简介 I/O即输入输出#xff0c;是计算机与外界世界的一个借口。IO操作的实际主题是操作系统。在java编程中#xff0c;一般使用流的方式来处理IO#xff0c;所有的IO都被视作是单个字节的移动#xff0c;通过stream对象一次移动一个字节。流IO负责把对象…一、基本概念 1、I/0简介 I/O即输入输出是计算机与外界世界的一个借口。IO操作的实际主题是操作系统。在java编程中一般使用流的方式来处理IO所有的IO都被视作是单个字节的移动通过stream对象一次移动一个字节。流IO负责把对象转换为字节然后再转换为对象。 关于Java IO相关知识请参考我的另一篇文章Java IO 详解 2、什么是NIO NIO即New IO这个库是在JDK1.4中才引入的。NIO和IO有相同的作用和目的但实现方式不同NIO主要用到的是块所以NIO的效率要比IO高很多。
在Java API中提供了两套NIO一套是针对标准输入输出NIO另一套就是网络编程NIO本篇文章重点介绍标NIO关于网络编程NIO请见Java NIO详解二。 3、流与块的比较 NIO和IO最大的区别是数据打包和传输方式。IO是以流的方式处理数据而NIO是以块的方式处理数据。 面向流的IO一次一个字节的处理数据一个输入流产生一个字节一个输出流就消费一个字节。为流式数据创建过滤器就变得非常容易链接几个过滤器以便对数据进行处理非常方便而简单但是面向流的IO通常处理的很慢。 面向块的IO系统以块的形式处理数据。每一个操作都在一步中产生或消费一个数据块。按块要比按流快的多但面向块的IO缺少了面向流IO所具有的有雅兴和简单性。 二、NIO基础 Buffer和Channel是标准NIO中的核心对象网络NIO中还有个Selector核心对象几乎每一个IO操作中都会用到它们。
Channel是对原IO中流的模拟任何来源和目的数据都必须通过一个Channel对象。一个Buffer实质上是一个容器对象发给Channel的所有对象都必须先放到Buffer中同样的从Channel中读取的任何数据都要读到Buffer中。 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() 方法只会清除已经读过的数据。任何未读的数据都被移到缓冲区的起始处新写入的数据将放到缓冲区未读数据的后面。
Buffer主要有如下几种 3、关于Channel
Channel是一个对象可以通过它读取和写入数据。可以把它看做IO中的流。但是它和流相比还有一些不同 1Channel是双向的既可以读又可以写而流是单向的 2Channel可以进行异步的读写 3对Channel的读写必须通过buffer对象 正如上面提到的所有数据都通过Buffer对象处理所以您永远不会将字节直接写入到Channel中相反您是将数据写入到Buffer中同样您也不会从Channel中读取字节而是将数据从Channel读入Buffer再从Buffer获取这个字节。 因为Channel是双向的所以Channel可以比流更好地反映出底层操作系统的真实情况。特别是在Unix模型中底层操作系统通常都是双向的。 在Java NIO中Channel主要有如下几种类型 FileChannel从文件读取数据的DatagramChannel读写UDP网络协议数据SocketChannel读写TCP网络协议数据ServerSocketChannel可以监听TCP连接 三、从理论到实践NIO中的读和写 IO中的读和写对应的是数据和StreamNIO中的读和写则对应的就是通道和缓冲区。NIO中从通道中读取创建一个缓冲区然后让通道读取数据到缓冲区。NIO写入数据到通道创建一个缓冲区用数据填充它然后让通道用这些数据来执行写入。 1、从文件中读取 我们已经知道在NIO系统中任何时候执行一个读操作您都是从Channel中读取而您不是直接从Channel中读取数据因为所有的数据都必须用Buffer来封装所以您应该是从Channel读取数据到Buffer。
因此如果从文件读取数据的话需要如下三步 1从FileInputStream获取Channel 2创建Buffer 3从Channel读取数据到Buffer
下面我们看一下具体过程
第一步获取通道 FileInputStream fin new FileInputStream( readandshow.txt );
FileChannel fc fin.getChannel(); 第二步建立缓冲区 ByteBuffer buffer ByteBuffer.allocate( 1024 );
第三步将数据从通道读到缓冲区fc.read( buffer ); 2、写入数据到文件类似于从文件读数据
第一步获取一个通道 FileOutputStream fout new FileOutputStream( writesomebytes.txt );
FileChannel fc fout.getChannel();
第二步创建缓冲区将数据放入缓冲区 ByteBuffer buffer ByteBuffer.allocate( 1024 );for (int i0; imessage.length; i) {buffer.put( message[i] );
}
buffer.flip();
第三步把缓冲区数据写入通道中 fc.write( buffer ); 3、读写结合CopyFile是一个非常好的读写结合的例子我们将通过CopyFile这个实力让大家体会NIO的操作过程。CopyFile执行三个基本的操作创建一个Buffer然后从源文件读取数据到缓冲区然后再将缓冲区写入目标文件。/*** 用java NIO api拷贝文件* param src* param dst* throws IOException*/
public static void copyFileUseNIO(String src,String dst) throws IOException{//声明源文件和目标文件FileInputStream finew FileInputStream(new File(src));FileOutputStream fonew FileOutputStream(new File(dst));//获得传输通道channelFileChannel inChannelfi.getChannel();FileChannel outChannelfo.getChannel();//获得容器bufferByteBuffer bufferByteBuffer.allocate(1024);while(true){//判断是否读完文件int eof inChannel.read(buffer);if(eof-1){break; }//重设一下buffer的position0limitpositionbuffer.flip();//开始写outChannel.write(buffer);//写完要重置buffer重设position0,limitcapacitybuffer.clear();}inChannel.close();outChannel.close();fi.close();fo.close();
} 四、需要注意的点上面程序中有三个地方需要注意 1、检查状态 当没有更多的数据时拷贝就算完成此时 read() 方法会返回 -1 我们可以根据这个方法判断是否读完。 int r fcin.read( buffer );
if (r-1) {break;
} 2、Buffer类的flip、clear方法
控制buffer状态的三个变量 1position跟踪已经写了多少数据或读了多少数据它指向的是下一个字节来自哪个位置 2limit代表还有多少数据可以取出或还有多少空间可以写入它的值小于等于capacity。 3capacity代表缓冲区的最大容量一般新建一个缓冲区的时候limit的值和capacity的值默认是相等的。
flip、clear这两个方法便是用来设置这些值的。 flip方法
我们先看一下flip的源码 public final Buffer flip() {limit position;position 0;mark -1;return this;} 在上面的FileCopy程序中写入数据之前我们调用了
buffer.flip();方法这个方法把当前的指针位置position设置成了limit再将当前指针position指向数据的最开始端我们现在可以将数据从缓冲区写入通道了。 position 被设置为 0这意味着我们得到的下一个字节是第一个字节。 limit 已被设置为原来的 position这意味着它包括以前读到的所有字节并且一个字节也不多。 clear方法
先看一下clear的源码 public final Buffer clear() {position 0;limit capacity;mark -1;return this;
} 在上面的FileCopy程序中写入数据之后也就是读数据之前我们调用了 buffer.clear();方法这个方法重设缓冲区以便接收更多的字节。上图显示了在调用 clear() 后缓冲区的状态。