java.nio基础篇之Buffer

来源:互联网 发布:淘宝好评率低而拒绝卖 编辑:程序博客网 时间:2024/05/19 17:48


很好的学习资料

http://tutorials.jenkov.com/java-nio/index.html


本文主要是对java.nio的全貌做个简单介绍 然后详细介绍Buffer方法 并测试Buffer的相关方法

Java nio (new io) 对于java io和 java networking而言,是一个可选的io api核心组件有三个Buffers Channels SelectorsBuffers缓存主要有ByteBuffer CharBuffer ShortBuffer IntBuffer FloatBuffer LongBuffer DoubleBuffer覆盖基本的数据类型  byte character short int float long doubleChannels通道主要有  FileChannel  DatagramChannel  ServerChannel  ServerSocketChannel包含file io、udp、tcp三类Selectors多路复用器或者称为选择器可以使一个线程使用多路复用器处理多个通道


Buffer与Channel的关系如下


对于Scatter与Gather模式的描述

A "scattering read" reads data from a single channel into multiple buffers
A "gathering write" writes data from multiple buffers into a single channel. 


两者的关系图





Channel与Selector的关系如下


下面是关于Buffer的各种方法的描述

Buffer中搞清楚 position  limit  capacity 的意思 在读写模式中的位置  理解Buffer的方法 就很简单了

Basic Buffer Usage源文档 <http://tutorials.jenkov.com/java-nio/buffers.html> 1. Write data into the Buffer2. Call buffer.flip()3. Read data out of the Buffer4. Call buffer.clear() or buffer.compact()源文档 <http://tutorials.jenkov.com/java-nio/buffers.html> Initially the position is 0,Position can maximally become capacity - 11. Write data from a Channel into a Buffer2. Write data into the Buffer yourself, via the buffer's put() methods.源文档 <http://tutorials.jenkov.com/java-nio/buffers.html> The flip() method switches a Buffer from writing mode to reading mode. Calling flip() sets the position back to 0, and sets the limit to where position just was.3. Read data from the buffer into a channel.4. Read data from the buffer yourself, using one of the get() methods.The Buffer.rewind() sets the position back to 0, so you can reread all the data in the buffer. The limit remains untouched, thus still marking how many elements (bytes, chars etc.) that can be read from the Buffer. clear() and compact()If you call clear() the position is set back to 0 and the limit to capacity. In other words, the Buffer is cleared. The data in the Buffer is not cleared. Only the markers telling where you can write data into the Buffer are.compact() copies all unread data to the beginning of the Buffer. Then it sets position to right after the last unread element. The limit property is still set to capacity, just like clear() does. Now the Buffer is ready for writing, but you will not overwrite the unread data. mark() and reset()You can mark a given position in a Buffer by calling the Buffer.mark() method. You can then later reset the position back to the marked position by calling the Buffer.reset() methodequals() and compareTo()equals()Two buffers are equal if: 5. They are of the same type (byte, char, int etc.)6. They have the same amount of remaining bytes, chars etc. in the buffer.7. All remaining bytes, chars etc. are equal.compareTo()The compareTo() method compares the remaining elements (bytes, chars etc.) of the two buffers, for use in e.g. sorting routines. A buffer is considered "smaller" than another buffer if: 8. The first element which is equal to the corresponding element in the other buffer, is smaller than that in the other buffer.9. All elements are equal, but the first buffer runs out of elements before the second buffer does (it has fewer elements).源文档 <http://tutorials.jenkov.com/java-nio/buffers.html> 

上面都是每个方法比较重要的描述 

Buffer的读模式与写模式的 position  limit capacity 三者间的关系图





最后一一些单元测试  都加了代码注释

package com.undergrowth;import java.io.FileNotFoundException;import java.io.IOException;import java.io.RandomAccessFile;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;import java.nio.charset.Charset;import org.junit.After;import org.junit.Before;import org.junit.Test;public class BasicChannel {RandomAccessFile randomAccessFile,randomAccessFile2;FileChannel fileChannel,fileChannel2;ByteBuffer buffer, buffer2;/** * 测试之前打开文件 分配buffer *  * @throws FileNotFoundException */@Beforepublic void before() throws FileNotFoundException {randomAccessFile = new RandomAccessFile(ClassLoader.getSystemResource("channel.xml").getFile(), "rw");randomAccessFile2 = new RandomAccessFile(ClassLoader.getSystemResource("channel2.xml").getFile(), "rw");fileChannel = randomAccessFile.getChannel();fileChannel2 = randomAccessFile2.getChannel();buffer = ByteBuffer.allocate(1024);buffer2 = ByteBuffer.allocate(512);}/** * 测试完成后 关闭文件 *  * @throws IOException */@Afterpublic void after() throws IOException {fileChannel.close();fileChannel2.close();randomAccessFile.close();randomAccessFile2.close();}/** * 测试读写 */@Testpublic void testRead() {// TODO Auto-generated method stubtry {System.out.println(readBuffer(fileChannel, buffer));} catch (Exception e) {// TODO: handle exceptione.printStackTrace();}}/** * 测试标记与重置 You can mark a given position in a Buffer by calling the * Buffer.mark() method. You can then later reset the position back to the * marked position by calling the Buffer.reset() method *  * @throws IOException */@Testpublic void testMarkReset() throws IOException {int byteRead = fileChannel.read(buffer);if (byteRead != -1) {// 反转buffer模式buffer.flip();while (buffer.hasRemaining()) {char tmp = (char) buffer.get();// 当出现9字符的时候 进行标注if (tmp == '9')buffer.mark();System.out.print(tmp);}// 将buffer的position置为9字符的位置buffer.reset();System.out.println();System.out.println("置为9字符的起始位置开始读取数据");while (buffer.hasRemaining())System.out.print((char) buffer.get());}}/** * 测试equals和compareTo 这两个方法都是比较剩余元素 equals() Two buffers are equal if: 5. * They are of the same type (byte, char, int etc.) 6. They have the same * amount of remaining bytes, chars etc. in the buffer. 7. All remaining * bytes, chars etc. are equal. *  * compareTo() The compareTo() method compares the remaining elements * (bytes, chars etc.) of the two buffers, for use in e.g. sorting routines. * A buffer is considered "smaller" than another buffer if: 8. The first * element which is equal to the corresponding element in the other buffer, * is smaller than that in the other buffer. 9. All elements are equal, but * the first buffer runs out of elements before the second buffer does (it * has fewer elements). *  * @throws IOException */@Testpublic void testEqualsCompare() throws IOException {int byteRead = fileChannel.read(buffer);buffer2.put((byte) 'q');int byteRead2 = fileChannel.read(buffer2);if (byteRead != -1 && byteRead2 != -1) {buffer.flip();buffer2.flip();System.out.println("剩下元素");System.out.println(buffer.remaining());System.out.println(buffer2.remaining());// 比较两个buffer是否相等System.out.println();System.out.println(buffer.equals(buffer2));System.out.println(buffer.compareTo(buffer2));}}/** * 测试重置方法 The Buffer.rewind() sets the position back to 0, so you can reread * all the data in the buffer. The limit remains untouched, thus still * marking how many elements (bytes, chars etc.) that can be read from the * Buffer. *  * @throws IOException */@Testpublic void testRewind() throws IOException {int byteRead = fileChannel.read(buffer);if (byteRead != -1) {// 反转buffer模式buffer.flip();while (buffer.hasRemaining())System.out.print((char) buffer.get());// 重新读取bufferSystem.out.println();System.out.println("重新读取buffer");// 将buffer的positon置为0buffer.rewind();while (buffer.hasRemaining())System.out.print((char) buffer.get());}}/** * 将文件通道的内容读入到缓存中 从缓存中读出数据 返回 If you call clear() the position is set back * to 0 and the limit to capacity. In other words, the Buffer is cleared. * The data in the Buffer is not cleared. Only the markers telling where you * can write data into the Buffer are. *  *  * compact() copies all unread data to the beginning of the Buffer. Then it * sets position to right after the last unread element. The limit property * is still set to capacity, just like clear() does. Now the Buffer is ready * for writing, but you will not overwrite the unread data. *  * @param fileChannel * @param buffer * @return * @throws IOException */public String readBuffer(FileChannel fileChannel, ByteBuffer buffer)throws IOException {StringBuilder builder = new StringBuilder();// 1、读入数据到缓存中int byteRead = fileChannel.read(buffer);while (byteRead != -1) {// 2、转换缓存的模式buffer.flip();// 3、从缓存中读出数据while (buffer.hasRemaining())builder.append((char) buffer.get());// 4、清除缓冲区buffer.clear();byteRead = fileChannel.read(buffer);}// System.out.println(builder.toString());return builder.toString();}@Testpublic void testWriteBuffer() throws IOException{buffer.put((byte)'1');buffer.put((byte)'2');buffer.put((byte)'3');buffer.put((byte)'4');System.out.println(fileChannel.write(buffer));}/** * Scatter和Gather模式 * Scatter Read支持从一个通道读取到多个缓存区 * Gather Write支持从多个缓存区将数据写入到一个通道中 * @throws IOException */@Testpublic void testScatterGather() throws IOException{//构建buffer数组ByteBuffer[] buffers={buffer,buffer2};//读数据到多个缓存中System.out.println(fileChannel.read(buffers));;//转换缓存模式buffer.flip();buffer2.flip();//读取缓存数据System.out.println("缓存1");while(buffer.hasRemaining()) System.out.print((char)buffer.get());        buffer.rewind();        System.out.println();        System.out.println("缓存1和2");        while(buffer.hasRemaining()) System.out.print((char)buffer.get());while(buffer2.hasRemaining()) System.out.print((char)buffer2.get());buffer.rewind();buffer2.rewind();System.out.println();System.out.println("字符集输出");System.out.println(Charset.defaultCharset().decode(buffer));buffer.rewind();buffer2.rewind();//写缓存数据fileChannel2.write(buffers);}/** * 从一个通道转换到另一个通道 * @throws IOException */@Testpublic void testChannerTransfer() throws IOException{System.out.println(fileChannel2.transferFrom(fileChannel, 0, fileChannel.size()));;}}





0 0
原创粉丝点击