JAVA的NIO的新特性和小Demo,进一步了解NIO
1.为什么要用NIO
NIO 的创建目的是为了让 Java 程序员可以实现高速 I/O 而无需编写自定义的本机代码。NIO 将最耗时的 I/O 操作(即填充和提取缓冲区)转移回操作系统,因而可以极大地提高速度。 原来的 I/O 库(在 java.io.*中) 与 NIO 最重要的区别是数据打包和传输的方式。正如前面提到的,原来的 I/O 以流的方式处理数据,而 NIO 以块的方式处理数据。
2.NIO核心对象:缓冲区
什么是缓冲区? Buffer 是一个对象, 它包含一些要写入或者刚读出的数据。 在 NIO 中加入 Buffer 对象,体现了新库与原 I/O 的一个重要区别。在面向流的 I/O 中,您将数据直接写入或者将数据直接读到 Stream 对象中。 在 NIO 库中,所有数据都是用缓冲区处理的。在读取数据时,它是直接读到缓冲区中的。在写入数据时,它是写入到缓冲区中的。任何时候访问 NIO 中的数据,您都是将它放到缓冲区中。
最常用的缓冲区类型是 ByteBuffer。一个 ByteBuffer 可以在其底层字节数组上进行 get/set 操作(即字节的获取和设置)。
3.NIO核心对象:通道
什么是通道? Channel是一个对象,可以通过它读取和写入数据。拿 NIO 与原来的 I/O 做个比较,通道就像是流。 正如前面提到的,所有数据都通过 Buffer 对象来处理。您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区。同样,您不会直接从通道中读取字节,而是将数据从通道读入缓冲区,再从缓冲区获取这个字节。
通道类型: 通道与流的不同之处在于通道是双向的。而流只是在一个方向上移动(一个流必须是 InputStream 或者 OutputStream 的子类), 而 通道 可以用于读、写或者同时用于读写。
实例:
NIO读文件
@Test public void read() throws Exception { //第一步是获取通道,我们从FileInpustream获取通道 FileInputStream fin = new FileInputStream("C:\\Users\\Administrator\\Desktop\\Test.txt"); FileChannel channel = fin.getChannel(); //下一步是创建缓冲区 ByteBuffer buf = ByteBuffer.allocate(1024); StringBuilder sb = new StringBuilder(); //通过通道读取文件内容到缓冲区,未读到文件最后就一直读取 while ((channel.read(buf)) != -1) { //调用flip之后,读到指针到缓存头部,并且设置最多只能读出之前写入的数据长度(而不是整个缓存容量的大小) buf.flip(); //循环判断缓冲区是否还有可用数据 while (buf.hasRemaining()) { char b = (char) buf.get(); sb.append(b); //读取缓冲区内容,转换成CHAR型 } System.out.println(String.valueOf(sb)); //compact():只会清除已经读过的数据 任何未读的数据都被移到缓冲区的其实出 //新写入的数据将放到缓冲区未读数据的后面 buf.compact(); } }
NIO写文件
@Test public void write() throws IOException { String mess[] = {"09","099","665","655","355"}; //创建文件字节输出流 FileOutputStream fout = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\Test2.txt"); //从字节流中获取通道 FileChannel channel = fout.getChannel(); //创建缓冲区对象 (allocate分配) ByteBuffer buffer = ByteBuffer.allocate(1024); //通过管道往缓冲区写数据 for (int i = 0; i <mess.length ; i++) { buffer.put(mess[i].getBytes()); } //改变缓冲区指针 buffer.flip(); //把缓冲区内容写入到通道 channel.write(buffer); //紧凑 buffer.compact(); //关流 fout.close(); }
NIO读写结合
@Test public void Nio() throws IOException { //创建字节输入流 FileInputStream fin = new FileInputStream("C:\\Users\\Administrator\\Desktop\\Test.txt"); //创建字节输出流 FileOutputStream fout = new FileOutputStream("C:\\Users\\Administrator\\Desktop\\Test3.txt"); //创建输入通道 FileChannel finChannel = fin.getChannel(); //创建输出通道 FileChannel foutChannel = fout.getChannel(); //创建Nio的缓冲流 ByteBuffer buffer = ByteBuffer.allocate(1024); //循环 while (true) { //clear方法重置缓冲区,使他可以接受读入的数据()position buffer.clear(); //从输入通道读取内容到缓冲区 int r = finChannel.read(buffer); //如果读取到文件的结尾 返回的结果为-1 if (r == -1){ break; } //flip()方法可以一步步读取缓冲区的内容 buffer.flip(); foutChannel.write(buffer); } //关流 fin.close(); fout.close(); }