16、New IO

16、New IO

1、为什么要使用NIO
NIO是JDK1.4加入发新包,NIO的创建目的是为了让java程序员可以实现高速I/O而无需编写自定义的本机代码。NIO将最耗时的I/O操作(即填充和提取缓冲区)转移回操作系统,因而可以极大的提高速度
2、流与块的比较
原来的I/O库与NIO最重要的区别是数据打包和传输的方式,原来的I/O以流的方式处理数据。而NIO以块的方式来处理数据
面向流的I/O系统一次一个字节的处理数据,一个输入流产生一个字节的数据,一个输出流消耗一个字节的数据,不利的一面是,面向流的I/O通常很慢
一个面向块的I/O系统以块的形式处理数据,每一个操作都作在下一步产生或者消耗一个数据块,按块处理数据比按字节处理数据要快很多,但是面向块的I/O缺少一下面向流的I/O所具有的优雅和简单。
3、缓冲区
在NIO中,所有数据都是用缓冲区处理的,在读取数据时,它直接读到缓冲区中,在写入数据时,她是写入到缓冲区中的,任何时候访问NIO中的数据,都是将它放入缓冲区中
缓冲区实质是一个数组,通常它是一个字节数组,但是也可以使用其他种类的数组,但是缓冲区不仅仅是一个数组,缓冲区提供了对数据的结构化访问,而且可以跟踪系统的读写进程
4、缓冲区类型
最常用的缓冲区类型是ByteBuffer,一个ByteBuffer可以在其底层字节数组上进行get/set操作(即字节的读取和设置)。ByteBuffer不是NIO中唯一的缓冲区类型,事实上每一种基本类型都有一个缓冲区类型
ByteBuffer
CharBuffer
ShortBuffer
IntBuffer
LongBuffer
FloatBuffer
DoubleBuffer
16、New IO

import java.nio.ByteBuffer;

public class NIODemo {

	public static void main(String[] args) {

		//创建一个字节缓冲区,申请内存空间为8字节allocate(分配)
		ByteBuffer buf=ByteBuffer.allocate(8);
		
		System.out.println("position="+buf.position());
		System.out.println("limit="+buf.limit());
		System.out.println("capacity="+buf.capacity());
		
		System.out.println("~~~~~~~~~~~~~");
		
		//向缓冲区写入数据
		buf.put((byte)10);
		buf.put((byte)20);
		buf.put((byte)30);
		buf.put((byte)40);
		System.out.println("position="+buf.position());
		System.out.println("limit="+buf.limit());
		System.out.println("capacity="+buf.capacity());
		
		//缓冲区的反转
		buf.flip();
		System.out.println("~~~~~~~~~~~~~");
		System.out.println("position="+buf.position());
		System.out.println("limit="+buf.limit());
		System.out.println("capacity="+buf.capacity());
		
		//hasRemaining告知当前位置和限制之间是否有元素
		if(buf.hasRemaining()) {
			//remaining返回当前位置与限制之间的元素数
			for(int i=0;i<buf.remaining();i++) {
				byte b=buf.get(i);
				System.out.println(b);
			}
		}
		
		System.out.println("~~~~~~~~~~~~~");
		System.out.println("position="+buf.position());
		System.out.println("limit="+buf.limit());
		System.out.println("capacity="+buf.capacity());
	}

}

position=0
limit=8
capacity=8
·············
position=4
limit=8
capacity=8
··········
position=0
limit=4
capacity=8
10
20
30
40
···········
position=0
limit=4
capacity=8

Buffer源码
16、New IO
5、通道:Channel

Channel是一个对象,可以通过它读取和写入数据,拿NIO和原来的I/O做一个比较,通道就是一个流。
正如前面踢到的,所有数据都通过Buffer对象来处理,您永远不会将字节直接写入通道中,相反,您是将数据写入包含一个或者多个字节的缓冲区,同样,您不会 直接从通道中读取字节,而是将数据从通道读入缓冲区,再从很清楚获取这个字节
16、New IO

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;

import javax.swing.Icon;

/*
 * 比较IO操作的性能比较
 * 1、内存映射最快
 * 2、NIO读写文件
 * 3、使用缓冲的IO流
 * 
 */

public class CopyFileDemo {
	
	
	private static void randomAccessFileCopy() throws Exception {
		RandomAccessFile in=new RandomAccessFile("d:\\液化.jpg","r");
		RandomAccessFile out=new RandomAccessFile("d:\\test\\液化.jpg","rw");
		
		FileChannel fcIn=in.getChannel();
		FileChannel fcOut=out.getChannel();
		
		long size=fcIn.size();//输入流的字节大小
		//输入流的缓冲区
		MappedByteBuffer inBuf=fcIn.map(MapMode.READ_ONLY,0, size);
		//输出流的缓冲区
		MappedByteBuffer outBuf=fcOut.map(MapMode.READ_WRITE,0, size);
		
		for(int i=0;i<size;i++) {
			outBuf.put(inBuf.get());
		}
		//关闭通道是会写入数据块
		fcIn.close();
		fcOut.close();
		in.close();
		out.close();
		System.out.println("copy success");
		
	}
	
	/*
	 * 通过文件通道实现文件的复制
	 */
	public static void copyFile() throws Exception {
		
			//创建一个输入文件的通道
			FileInputStream fis=new FileInputStream("d:\\液化.jpg");
			FileChannel fcIn=fis.getChannel();
			
			//创建一个输出文件的通道
			FileOutputStream fos=new FileOutputStream("d:\\test\\液化.jpg");
			FileChannel fcOut=fos.getChannel();
			
			ByteBuffer buf=ByteBuffer.allocate(1024);
			while(fcIn.read(buf)!=-1) {
				//反转
				buf.flip();
				fcOut.write(buf);
				buf.clear();
			}
			
			fcIn.close();
			fcOut.close();
			System.out.println("copy success");
		
	}

	public static void main(String[] args) {

		try {
			//copyFile();
			randomAccessFileCopy();
		} catch (Exception e) {
			e.printStackTrace();
		}
	}

}

上一篇:Node.js Buffer库基础函数


下一篇:MHOOK的使用