NIO中两个核心对象为Channel(通道)和Buffer(缓冲)
Buffer,ByteBuffer,CharBuffer,DoubleBuffer,FloatBuffer,IntBuffer,LongBuffer,ShortBuffer,MappedByteBuffer(ByteBuffer的子类)
实例化Buffer的方法(MappedByteBuffer除外):
ByteBuffer bb = ByteBuffer.allocate(capacity);
capacity为缓冲区容量。
对Buffer属性的一系列操作:
public static void BufferTest() {
//创建普通的buffer
ByteBuffer bb = ByteBuffer.allocate(8);
//创建直接buffer和普通buffer对比是创建成本高,I/O操作较快
ByteBuffer bb2 = ByteBuffer.allocateDirect(8);
//buffer的三属性 关系为 容量cap>=界限lim>=位置pos
//容量
bb.capacity();
//界限
bb.limit();
//位置
bb.position();
/*
* 向普通buffer中存入元素,position随添加的元素而增涨初始为0
* pos=0 lim=8 cap=8
*/
bb.put((byte) 'a');
bb.put((byte) 'b');
/*
* pos=2 lim=8 cap=8
* buffer为非空调用flip()为输出做准备
* 执行flip()后 limit指到有效长度position指到0的位置
*/
bb.flip();
/*
* pos=0 lim=2 cap=8
* 输出数据结束后调用clear()为下次输入做准备
* 执行clear()后 limit指到capacity位置position指到0位置
*/
bb.clear();
/*
* pos=0 lim=8 cap=8
* 如果再添加c元素到buffer 这时的position应该向后+1,并且覆盖掉原来的a
*/
bb.put((byte) 'c');
//pos=1 lim=8 cap=8
}
Channel类
通过下面这个方法来了解:
/**
* 传统的IO效率不高因为是依赖与字节来处理
* nio是依赖于映射内存区块来处理处理效率高
* 该方法典型的就是oc.write(mbbuffer);
* mbbuffer是Struts2Test.java的缓冲区块,这里是直接整块写出
* 传统的一般会类似:
* String str = "";
* while(str = buffer.readLine() != null) {
* xxx.write(str);
* }
*/
public static void channelTest() throws IOException {
/*
* Channel的实现类有:
* java.nio.channels包下
* DatagramChannel,FileChannel,SelectableChannel
* ServerSocketChannel,SocketChannel(支持tcp网络通信的管道)
* java.nio.channels.Pipe包下
* SinkChannel,SourceChannel(线程之间的通信管道)
*/
//创建Channel实例 一般通过节点流创建Channel
File fileIn = new File("F:"+File.separator+"testSource"+File.separator+"Struts2Test.java");
File fileOut = new File("F:"+File.separator+"testSource"+File.separator+"nioTest.txt");
//创建节点流
FileInputStream fis = new FileInputStream(fileIn);
FileOutputStream fos = new FileOutputStream(fileOut);
//创建Channel
FileChannel ic = fis.getChannel();
FileChannel oc = fos.getChannel();
//Channel常用三方法map write read
//通过map方法把Channel包装成Buffer
MappedByteBuffer mbbuffer = ic.map(MapMode.READ_ONLY, 0, fileIn.length());
//Channel只能与buffer交互不能直接访问Channel的数据
oc.write(mbbuffer);
mbbuffer.clear();
ic.close();
oc.close();
}
Channel的read类似write操作
如果在noiTest.txt文件末尾追加Struts2Test.java的内容,可以在上面代码中
26行改为
//追加到文件末尾
FileOutputStream fos = new FileOutputStream(fileOut, true);
32、33行之间加入
oc.position(fileOut.length());
结合Buffer的position属性不难推知这句代码的含义
编码解码就是ByteBuffer和CharBuffer之间的转换
Char转Byte为编码 反之为解码
下面代码简单说明了编码和解码:
public static void main(String[] args) throws CharacterCodingException {
//Encode编码(Char->Byte) Decode解码(Byte->Char)
//获取Charset
Charset cs = Charset.forName("GBK");
//实例化普通Buffer
CharBuffer cb =CharBuffer.allocate(8);
cb.put("牛");
cb.put("羊");
cb.put("马");
cb.flip();
//Charset自带编码
ByteBuffer bb = cs.encode(cb);
for(int i=0;i<bb.capacity();i++) {
System.out.println(bb.get(i)+"\t");
}
System.out.println();
//Charset自带解码
CharBuffer cbNext = cs.decode(bb);
System.out.println(cbNext);
//编码 nio
CharsetEncoder ce = cs.newEncoder();
ByteBuffer niobb = ce.encode(cbNext);
for(int i=0;i<niobb.capacity();i++) {
System.out.println(niobb.get(i)+"\t");
}
//解码 nio
CharsetDecoder cd = cs.newDecoder();
CharBuffer niocb = cd.decode(niobb);
System.out.println(niocb);
}
}
上面代码分别说明了两种编码和解码