在NIO库中,所有数据都是用缓冲区处理的。每一个java基本类型都提供了对应的缓冲区类型,并且每个缓冲类型都是继承Buffer接口的一个实例。除了ByteBuffer以外,其他缓冲类型都提供了完全一样的操作。
下面我们通过ByteBuffer的内部细节来了解,缓冲类型的操作与转换。
ByteBuffer状态变量:
position、limit、capacity这三个值制定了缓冲区在任意时刻的状态。
position:用来跟踪已经写了多少数据,他指定了下一个字节将放到数组的那一个元素中。例如,如果你要你从通道中读三个字节到缓冲区中,那么缓冲区的position将会设置为3,指向数组中第四个元素。同样在写入通道中,position值跟踪从缓冲区中获取了多少数据,它指定了下一个字节来自数组的那一个元素。
limit:表面了缓冲区还有多少数据需要取出,或者还有多少空间可以放入数据。
capacity:表明了可以存储在缓冲区中最大数据容量。
ByteBuffer方法介绍:
一、状态控制
flip():这个方法首先他将limit设置为当前position,然后他将position设置为0。这意味着当使用了flip方法后我们可以获得position为0,limit为写入数据的长度的所有字节,即以写入到缓冲区中的所有字节数据。
clear():这个方法重设缓冲区以便接受更多的字节,他将limit设置为相同capacity,并将position设置为0,当调用了clear后,缓冲区可以接受新的数据了。
二、访问方法
get():从缓冲中读取字节,当入参为byte数组时,表示将缓冲中数据写入到指定长度的字节数组中。当进行读操作的时候,状态变量position会自动进位;
put():将字节放入到缓冲区中。
除了上面两个读写方法外,ByteBuffer还提供了对不同基本类型的值读写操作方法。例如:getByte(),getChar(),getLong(),putDouble(),putChar()....
在文件通道中(FileChannel)提供了read(),write(),通过clear()和flip()进行缓冲区在读写之间切换,简化了文件对缓冲区的读写操作。
例:实现将文件中内容写入到另外一个文件中去
- while(true){
- buffer.clear();
- int r = fileChannelIn.read(buffer);
- if(r==-1) break;
- buffler.flip();
- fileChannelOut.write(buffer);
- }
三、 缓冲区分配和包装
缓冲区分配:在能够读和写之前,必须有一个缓冲区。要创建缓冲区,你必须分配它。静态方法allocate()实现了分配一个具有指定大小的底层数组,并将它包装到一个缓冲区对象中。
例:此实例实现了将一个float类型转换为byte数组的操作。
- float v=12.11;
- ByteBuffer bb = ByteBuffer.allocate(4);
- byte[] ret = new byte[4];
- FloatBuffer fb = bb.asFloatBuffer();
- fb.put(v);
- bb.get(ret);
- return ret;
包装:你还可以将一个现有的数组转换为缓冲区。使用wrap()方法将一个数组包装为缓冲区,必须非常小心地进行这类操作,应为一旦完成包装,底层数据就可以通过缓冲区或者直接访问。
例:这个实例实现了将一个byte数组转换为float类型的数据
- byte[] v;
- ByteBuffer bb = ByteBuffer.wrap(v);
- FloatBuffer fb = bb.asFloatBuffer();
- return fb.get();
五、缓存区分片
slice()方法可以根据现有的缓冲区创建一个新的缓冲区,新缓冲区共享与原来的缓冲区的一部分数据。
五、字符集(编码/解码)
Charset是“十六位Unicode字符串序列与字节序列之间的一个命名映射”。他可以帮助你尽可能移植读写字符串序列。下面我们将介绍如何使用Charset来处理现代文本格式的方式处理文本数据。
1、编码(CharsetDecoder):用于将逐位表示的一串字符转换为具体的char值。
2、解码(CharsetEncoder):用于将字符转换回位。
以下示例,演示了如何将读入的文本,进行编码返回为字符串:
- file = new FileInputStream("TT.TXT");
- FileChannel fc = file.getChannel();
- ByteBuffer buffer = ByteBuffer.allocate(5000);
- fc.read(buffer);
- buffer.flip();
- try{
- Charset charset = Charset.forName("gb2312");
- CharsetDecoder decoder = charset.newDecoder();
- CharBuffer charBuffer = decoder.decode(buffer);
- return charBuffer.toString();
- } catch (Exception ex){
- ex.printStackTrace();
- return "" ;
- }