Java nio(二)

一、各种缓冲区: 
所有的缓冲区都继承了Buffer,Buffer类定义了所有缓冲区共有的基本特征,缓冲区存储了制定类型的元素序列有:ByteBuffer、CharBuffer、ShortBuffer、IntBuffer、LongBuffer、FloatBuffer、DoubleBuffer。 
我们需要知道这些基本类型占用存储空间与Byte的对应关系: 
char 2 bytes,int 4 bytes,double 8 bytes 
二、我们看看Buffer三个重要的概念以及他们之间的关系: 
capacity 所能存方特定类型值得最大数量 
limit 第一个不能读取或写入的索引位置 
position 下一个要读取或写入的缓冲区索引位置 
理解这三者的关系是对缓冲区操作的关键: 
新创建的一个缓冲区,position=0,limit=capacity 
我们可以通过position(int newPosition)和limit(int newLimit)来调整position和limit的值。显然0 =< position =< limit =< capacity,所以我们在设置这个位置 
需要小心,以满足这个条件,一般如果同时设置limit和position的时候,下面代码是一个 
安全的方法: 
Java代码   收藏代码
  1. buf.position(0).limit(newLimit).position(newPosition);  

position和capacity存在的理由不需要解释。 


为什么需要limit呢?这是理解缓冲区操作的关键所在。 
一段数据怎么去标示出来呢?两个点决定了一个段啊, 
而position就是起点,limit就是终点。但这个起点和终点在不同时候,他 
表示的含义不同: 
当把数据写入buffer时,poision到limit就是可以写的空间 
当从buffer读数据时,position到limit就是可读取的数据 
所以我们经常做的事情就是: 
把数据写入Buffer,,然后使用buf.flip()操作,最后把Buffer写入File中。这个过程发生了什么? 
我们把数据写入Buffer后,position为写入的最后一个数据的位置,而buf.flip()是 
buf.limit(buf.position()).position(0);的简写形式。这样position到limit就 
标示了可以写到文件的数据 


另外还有一个mark()方法,他记录了上一次position和limit的位置,通过reset()可以 
恢复到这个状态。 
三、下面我们看看如何创建缓冲区的: 
缓冲区类没有共有的构造方法,但提供了静态工厂方法allocate来创造缓冲区 
Java代码   收藏代码
  1. ByteBuffer buf = ByteBuffer.allocate(1024);  
  2. FloatBuffer buf = FloatBuffer.allocate(100);  
  3. //...  

我们可以通过wrap来把字节数组包装成ByteBuffer 
Java代码   收藏代码
  1. String str = "Hi,just a test";  
  2. byte[] arr = str.getBytes();  
  3. ByteBuffer buf = ByteBuffer.wrap(arr);  
  4. //ByteBuffer buf = ByteBuffer.wrap(arr,offset,len);  

四、视图缓存区: 
从名字我们可以知道这种缓冲区是为了提供方便操作的视图而存在的,从ByteBuffer可以 
得到各种基本类型(boolean除外)对应的缓冲区,这个过程是通过asXxBuffer()方法得到的。 
有了视图缓冲区我们就可以方便的对缓冲区进行操作了,所做的操作直接影响后备缓冲区(ByteBuffer)的数据,但不影响后备缓冲区的limit和position.所以我们如果这时候 
在想把后备缓冲区写入文件的时候,需要手工调整limit值。 
五、缓冲区数据的传送: 
1、将数据送到缓冲区: 
ByteBuffer有两种put操作(相对的和决对的),用来传送数据到缓冲区: 
Java代码   收藏代码
  1. put(byte b);  
  2. put(int index,byte b);  
  3. put(byte[] array,int offset,int len);  
  4. put(ByteBuffer src);  

例子: 
Java代码   收藏代码
  1. String text = "Value of e";  
  2. ByteBuffer buf = ByteBuffer.allocate(text.length() + sizeof(Math.E));  
  3. buf.put(text.getBytes()).putDouble(Math.E);  

这个例子会用本地的编码获的字节数组。 
而如果要想以原来Unicode字符码的形式传递的话,可以这么写: 
Java代码   收藏代码
  1. char[] array = text.toCharArray();  
  2. ByteBuffer buf = ByteBuffer.allocate(50);  
  3. for(char ch : array)  
  4.   buf.putChar(ch);  
  5. buf.putDouble(Math.E);  

六、写文件 
我们把数据写入缓冲区和上次我们总结的用Channel把缓冲区的数据写入文件合起来就可以写文件了: 
Java代码   收藏代码
  1. String text = "Value of e";  
  2. ByteBuffer buf = ByteBuffer.allocate(text.length() + sizeof(Math.E));  
  3. buf.put(text.getBytes()).putDouble(Math.E);  
  4. buf.flip();  
  5. File file = new File("D:\test.txt");  
  6. FileOutputStream fos = new FileOutputStream(file);  
  7. FileChannle outputChannel = fos.getChannel();  
  8. outputChannel.write(buf);  
  9. fos.close();  

六、使用视图缓冲区: 
前面我们介绍了视图缓冲区,我们看看使用视图缓冲区写文件的例子: 
Java代码   收藏代码
  1. String greeting = "Hi,nice to meet you!";  
  2. ByteBuffer buf = ByteBuffer.allocate(1024);  
  3. CharBuffer charBuf = buf.asCharBuffer();//得到试图缓冲区  
  4. charBuf.put(greeting);//把字符串转换成Buffer,操作视图缓冲区  
  5. buf.limit(2*charBuffer.position());  
  6. FileChannel outputChannel = fos.getChannel();  
  7. fos.write(buf);  
  8. fos.close();  

七、集中写操作: 
文件通道有两个方法可以执行集中写操作: 
write(ByteBuffer[] buffers); 
write(ByteBuffer[] buffers,int offset,int length); 
把分散在多个buffer的数据集中写入文件 
我们看一个例子: 
Java代码   收藏代码
  1. String str = "hi,just a test";  
  2. dobule d = Math.E;  
  3. FileChannel outputChannel = fos.getChannel();  
  4. ByteBuffer[] buffers = new ByteBuffer[2];  
  5. buffer[0] = ByteBuffer.allocate(str.length());  
  6. buffer[1] = ByteBuffer.allocate(sizeof(i));  
  7. buffer[0].put(str.getBytes).flip();  
  8. buffer[1].putDouble(d);  
  9. outputChannel.write(buffers);  
  10. fos.close();  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值