`
Donald_Draper
  • 浏览: 951415 次
社区版块
存档分类
最新评论

Java NIO ByteBuffer详解

    博客分类:
  • NIO
阅读更多
Java Socket编程实例:http://donald-draper.iteye.com/blog/2356695
java Socket读写缓存区Writer和Reader:http://donald-draper.iteye.com/blog/2356885
前一篇文章中,我们讲了java Socket io的Writer和Reader,在上一篇中,在流解码器和编码器中,经常用到字节缓冲ByteBuffer,今天我们就来看一ByteBuffer。
ByteBuffer有两个实现一个为,HeapByteBuffer,另一个为DirectByteBuffer,这两个有什么区别呢?
我们引入原文,不翻译以免都是原味;
1.HeapByteBuffer
//ByteBuffer,创建方法
 public static ByteBuffer allocate(int capacity) {
        if (capacity < 0)
            throw new IllegalArgumentException();
        return new HeapByteBuffer(capacity, capacity);
    }

HeapByteBuffer使用的java堆内存
2.DirectByteBuffer
//ByteBuffer,创建方法
public static ByteBuffer allocateDirect(int capacity) {
        return new DirectByteBuffer(capacity);
    }
* <p> A byte buffer is either <i>direct</i> or <i>non-direct</i>.  Given a
 * direct byte buffer, the Java virtual machine will make a best effort to
 * perform native I/O operations directly upon it.  That is, it will attempt to
 * avoid copying the buffer's content to (or from) an intermediate buffer
 * before (or after) each invocation of one of the underlying operating
 * system's native I/O operations.
 *
 * <p> A direct byte buffer may be created by invoking the {@link
 * #allocateDirect(int) allocateDirect} factory method of this class.  The
 * buffers returned by this method typically have somewhat higher allocation
 * and deallocation costs than non-direct buffers.  The contents of direct
 * buffers may reside outside of the normal garbage-collected heap, and so
 * their impact upon the memory footprint of an application might not be
 * obvious.  It is therefore recommended that direct buffers be allocated
 * primarily for large, long-lived buffers that are subject to the underlying
 * system's native I/O operations.  In general it is best to allocate direct
 * buffers only when they yield a measureable gain in program performance.
 *
 * <p> A direct byte buffer may also be created by {@link
 * java.nio.channels.FileChannel#map </code>mapping<code>} a region of a file
 * directly into memory.  An implementation of the Java platform may optionally
 * support the creation of direct byte buffers from native code via JNI.  If an
 * instance of one of these kinds of buffers refers to an inaccessible region
 * of memory then an attempt to access that region will not change the buffer's
 * content and will cause an unspecified exception to be thrown either at the
 * time of the access or at some later time.


DirectByteBuffer使用的是:the Java virtual machine will make a best effort to
perform native I/O operations directly upon it.
使用时要注意:It is therefore recommended that direct buffers be allocated
primarily for large, long-lived buffers that are subject to the underlying
system's native I/O operations


今天我们只讲HeapByteBuffer,ByteBuffer,Buffer,我们先从测试实例来看
 public abstract class Buffer {

    // Invariants: mark <= position <= limit <= capacity
    private int mark = -1;//标记,用于reset函数,是复位position到mark位置
    private int position = 0;//Buffer缓冲区读写位置
    private int limit;//读写上限
    private int capacity;//缓冲区容量
    }


mark,position,limit,capacity大小关系:

-1 <= mark <= position <= limit <= capacity;
0<= position <= limit <= capacity;



测试主类:


 package socket;

import java.nio.BufferOverflowException;
import java.nio.ByteBuffer;
/**
 * 测试ByteBuffer
 * @author donald
 * 2017年2月14日
 * 下午5:23:32
 */
public class TestByteBuffer {
	private static ByteBuffer byteBuffer = null;
	public  static void main(String[] args) {
		    /* 以下顺序不要改变*/
			initByteBuffer();
			testByte(); 
			testChar(); 
			testMark();
			testInt();
			testFloat(); 
			testDouble();
			testLong();
			testRemaining();
			testOverFlow();
			testReset();
			testClear();
//			testCompact();
	}
	/**
	 * 初始化缓存空间
	 */
	 public static void initByteBuffer(){
		 byteBuffer  = ByteBuffer.allocate(32);
         System.out.println("===============init status============");
         System.out.println("position:"+byteBuffer.position());
         System.out.println("limit:"+byteBuffer.limit());
         System.out.println("capacity:"+byteBuffer.capacity());
	  }
	 /**
	  * 测试Byte,占用一个字节
	  */
	 public static void testByte(){
   	  	 System.out.println("===============put byte============");
         //字节
         byte bbyte = 102;
         byteBuffer.put(bbyte);//ByteBuffer
         byteBuffer.get(0);//byte
         System.out.println("position:"+byteBuffer.position());
         System.out.println("limit:"+byteBuffer.limit());
         System.out.println("capacity:"+byteBuffer.capacity());
         System.out.println("======get byte:"+byteBuffer.get(0));
     }
	 /**
	  * 测试Char,占用2个字节
	  */
	 public static void testChar(){
   	  System.out.println("===============put char============");
         //字符
         char aChar= 'a';
         byteBuffer.putChar(aChar);
         System.out.println("position:"+byteBuffer.position());
         System.out.println("limit:"+byteBuffer.limit());
         System.out.println("capacity:"+byteBuffer.capacity());
         System.out.println("======get Char:"+byteBuffer.getChar(1));
     }
	 /**
	  * 标记位置,以便reset,返回这个标记位置
	  */
	  public static void testMark(){
    	  //标记位置
          byteBuffer.mark();
          System.out.println("===============mark============");
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
      }
	  /**
	   * 测试int,占用4个字节
	   */
	  public static void testInt(){
    	  System.out.println("===============put int============");
          //int
          int int4 = 4;
          byteBuffer.putInt(int4);
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          //这里为什么从第三个字节开始读取,因为前面一个字节和一个字符总共三个字节
          System.out.println("======get int:"+byteBuffer.getInt(3));
      }
	  /**
	   * 测试float,占用4个字节
	   */
	  public static void testFloat(){
    	  System.out.println("===============put float============");
          //float
          float float5 = 10;
          byteBuffer.putFloat(float5);
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          //这里为什么从第7个字节开始读取,因为前面一个字节和一个字符,一个int总共7个字节
          System.out.println("======get float:"+byteBuffer.getFloat(7));
      }
	  /**
	   * 测试double,占用8个字节
	   */
	  public static void testDouble(){
    	  System.out.println("===============put double============");
          //double
          double double6 = 20.0;
          byteBuffer.putDouble(double6);
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          //这里为什么从第11个字节开始读取,因为前面一个字节和一个字符,一个int,一个float总共11个字节
          System.out.println("======get double:"+byteBuffer.getDouble(11));
      }
	  /**
	   * 测试Long,占用8个字节
	   */
	  public static void testLong(){
    	  System.out.println("===============put long============");
          //long
          long long7 = (long) 30.0;
          byteBuffer.putLong(long7);
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          //这里为什么从第19个字节开始读取,因为前面一个字节和一个字符,一个int,一个float,一个double总共19个字节
          System.out.println("======get long:"+byteBuffer.getLong(19));
      }
	  /**
	   * 测试字节缓冲的剩余空间函数
	   */
	  public static void testRemaining(){
    	  System.out.println("======buffer 剩余空间大小:"+byteBuffer.remaining());
      }
	  /**
	   * 测试添加元素字节长度,大于剩余空间时的情况
	   */
	  public static void testOverFlow(){
    	  /*Exception in thread "main" java.nio.BufferOverflowException
	      	at java.nio.Buffer.nextPutIndex(Buffer.java:519)
	      	at java.nio.HeapByteBuffer.putLong(HeapByteBuffer.java:417)
	      	at socket.TestByteBuffer.main(TestByteBuffer.java:60)
	      	超出空间,则抛出BufferOverflowException异常
	      	*/
         try{
      	   byteBuffer.putLong((long)30.0);
         }
         catch(BufferOverflowException e){
      	   e.printStackTrace();
         }
      }
	  /**
	   * 测试回到标记,position为标记的mark
	   */
	  public static void testReset(){
     	 System.out.println("===============reset============");
          //回到mark标记位置,position为标记的mark
          byteBuffer.reset();
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          System.out.println("======get  int from mark:"+byteBuffer.getInt(3));
          //重新,从标记位置put一个int值,原来的内容被覆盖掉
          int int5 = 5;
          byteBuffer.putInt(int5);
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit());
          System.out.println("capacity:"+byteBuffer.capacity());
          System.out.println("======get int from mark after put new int value:"+byteBuffer.getInt(3));
      }
	  /**
	   * clear重置position,mark,limit位置,原始缓存区内容并不清掉
	   */
	  public static void testClear(){
    	  System.out.println("===============clear============");
          //clear重置position,mark,limit位置,原始缓存区内容并不清掉
          byteBuffer.clear();
          System.out.println("position:"+byteBuffer.position());
          System.out.println("limit:"+byteBuffer.limit()); 
          System.out.println("capacity:"+byteBuffer.capacity());
          System.out.println("======get int  after clear:"+byteBuffer.getInt(3));
          
      }
	  
	  public static void testCompact(){
			 System.out.println("===============compact============");
	            /*
	             * compact操作用于当
	             *  while (in.read(buf) >= 0 || buf.position != 0) {
	             *     buf.flip();
	             *     out.write(buf);
	             *     buf.compact();    // In case of partial write
	             *    }
	             * 当out发送数据,即读取buf的数据,write方法可能只发送了部分数据,buf里还有剩余,
	             * 这时调用buf.compact()函数将position与limit之间的数据,copy到buf的0到limit-position,进行压缩(非实际以压缩,只是移动),
	             * 以便下次 向写入缓存。
	             */
	           
	            byteBuffer.compact();
	            System.out.println("position:"+byteBuffer.position());
	            System.out.println("limit:"+byteBuffer.limit());
	            System.out.println("capacity:"+byteBuffer.capacity());
	            System.out.println("======get int:"+byteBuffer.getInt(3));
	            System.out.println("===============flip============");
	           /* 
	            * buf.put(magic);    // Prepend header
	            * in.read(buf);      // Read data into rest of buffer
	            * buf.flip();        // Flip buffer
	            * out.write(buf); 
	            * 当in从缓冲中读取数据后,如果想要将缓存中的数据发送出去,则调用buf.flip()函数,limit为当前position,position为0,
	            * /
//	            byteBuffer.flip();
	            System.out.println("===============rewind============");
	            /* 
	            * out.write(buf);    // Write remaining data
	            * buf.rewind();      // Rewind buffer
	            * buf.get(array);    // Copy data into array</pre></blockquote>
	            * 当out写出数据,即读取buf的数据后,如果想要从缓存中,从0位置,获取缓存数据,则调用buf.rewind()
	            */            
//	            byteBuffer.rewind();
	            
		}
      
}

注意 main里面方法的调用顺序不要变,第一次测试我们先注释掉testCompact方法,控制台输出:
===============init status============
position:0
limit:32
capacity:32
===============put byte============
position:1
limit:32
capacity:32
======get byte:102
===============put char============
position:3
limit:32
capacity:32
======get Char:a
===============mark============
position:3
limit:32
capacity:32
===============put int============
position:7
limit:32
capacity:32
======get int:4
===============put float============
position:11
limit:32
capacity:32
======get float:10.0
===============put double============
position:19
limit:32
capacity:32
======get double:20.0
===============put long============
position:27
limit:32
capacity:32
======get long:30
======buffer 剩余空间大小:5
java.nio.BufferOverflowException
at java.nio.Buffer.nextPutIndex(Buffer.java:519)
at java.nio.HeapByteBuffer.putLong(HeapByteBuffer.java:417)
at socket.TestByteBuffer.testOverFlow(TestByteBuffer.java:150)
at socket.TestByteBuffer.main(TestByteBuffer.java:24)
===============reset============
position:3
limit:32
capacity:32
======get  int from mark:4
position:7
limit:32
capacity:32
======get int from mark after put new int value:5
===============clear============
position:0
limit:32
capacity:32
======get int  after clear:5
从控制台输出可看出,ByteBuffer的put*和get*(int index)方法不改变mark,limit和capacity的值;put则回改变position的位置,put操作后position的位置为,put操作之前position+length(put 操作数);mark操作会改变mark的值,reset操作,则是将position定位到mark;clear操作并不会清空缓冲空间,而是将position复位0,limit为capacity,mark为-1;remain操作返回的是可用的空间大小为capacity-position;
如put后,超出缓冲区大小,则抛出BufferOverflowException异常。


下面我们将mark,reset和clear注释掉,测试Compact操作如下:
	public  static void main(String[] args) {
		    /* 以下顺序不要改变*/
			initByteBuffer();
			testByte(); 
			testChar(); 
//			testMark();
			testInt();
			testFloat(); 
			testDouble();
			testLong();
			testRemaining();
			testOverFlow();
//			testReset();
//			testClear();
			testCompact();
	}


关注控制的compact部分输出:
===============put long============
position:27
limit:32
capacity:32
======get long:30
======buffer 剩余空间大小:5
java.nio.BufferOverflowException
at java.nio.Buffer.nextPutIndex(Buffer.java:519)
at java.nio.HeapByteBuffer.putLong(HeapByteBuffer.java:417)
at socket.TestByteBuffer.testOverFlow(TestByteBuffer.java:150)
at socket.TestByteBuffer.main(TestByteBuffer.java:24)
===============compact============
position:5
limit:32
capacity:32
======get int:4
===============flip============
===============rewind============
从控制台输出可以看出,compact操作一般在一下情况调用,
 /*
 * compact操作用于当
 *  while (in.read(buf) >= 0 || buf.position != 0) {
 *     buf.flip();
 *     out.write(buf);
 *     buf.compact();    // In case of partial write
 *    }
 */

当out发送数据,即读取buf的数据,write方法可能只发送了部分数据,buf里还有剩余,
这时调用buf.compact()函数将position与limit之间的数据,copy到buf的0到limit-position,
进行压缩(非实际以压缩,只是移动),以便下次 向写入缓存。当position与limit之间的数据为空时,则不改变原缓冲区,否则copy相应数据。
//HeapByteBuffer
public ByteBuffer compact() {

        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
        position(remaining());
        limit(capacity());
        discardMark();
        return this;
    }

/*
If <code>src</code> is <code>null</code>, then a
* <code>NullPointerException</code> is thrown and the destination
* array is not modified.
*/
//System
 public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);



线面我们来看一下Buffer的相关操作:
public abstract class Buffer {

    // Invariants: mark <= position <= limit <= capacity
    private int mark = -1;
    private int position = 0;
    private int limit;
    private int capacity;

   //返回position
    public final int position() {
        return position;
    }
    //返回capacity
    public final int capacity() {
        return capacity;
    }
    //重新定义position位置,如mark位置大于新position,则废弃mark位置
    public final Buffer position(int newPosition) {
        if ((newPosition > limit) || (newPosition < 0))
            throw new IllegalArgumentException();
        position = newPosition;
        if (mark > position) mark = -1;
        return this;
    }
    //返回limit
     public final int limit() {
        return limit;
    }
    //标记位置
    public final Buffer mark() {
        mark = position;
        return this;
    }
    //复位position到mark位置
    public final Buffer reset() {
        int m = mark;
        if (m < 0)
            throw new InvalidMarkException();
        position = m;
        return this;
    }
    //clear操作并不会清空缓冲空间,而是将
    //position复位0,limit为capacity,mark为-1;
    public final Buffer clear() {
        position = 0;
        limit = capacity;
        mark = -1;
        return this;
    }
   /* 
    * buf.put(magic);    // Prepend header
    * in.read(buf);      // Read data into rest of buffer
    * buf.flip();        // Flip buffer
    * out.write(buf); 
    * 当in从缓冲中读取数据后,如果想要将缓存中的数据发送出去,
    * 则调用buf.flip()函数,limit为当前position,position为0,
    */
    public final Buffer flip() {
        limit = position;
        position = 0;
        mark = -1;
        return this;
    }
    /* 
     * out.write(buf);    // Write remaining data
     * buf.rewind();      // Rewind buffer
     * buf.get(array);    // Copy data into array</pre></blockquote>
     * 当out写出数据,即读取buf的数据后,如果想要从缓存中,从0位置,获取缓存数据,则调用buf.rewind()
     */      
    public final Buffer rewind() {
        position = 0;
        mark = -1;
        return this;
    }
    //返回可用空间
    public final int remaining() {
        return limit - position;
    }
    //废弃标记位置
    final void discardMark() {                          // package-private
        mark = -1;
    }
    Buffer(int mark, int pos, int lim, int cap) {       // package-private
        if (cap < 0)
            throw new IllegalArgumentException("Negative capacity: " + cap);
        this.capacity = cap;
        limit(lim);
        position(pos);
        if (mark >= 0) {
            if (mark > pos)
                throw new IllegalArgumentException("mark > position: ("
                                                   + mark + " > " + pos + ")");
            this.mark = mark;
        }
    }
}

再来看ByteBuffer
public abstract class ByteBuffer
    extends Buffer
    implements Comparable<ByteBuffer>
{

    // These fields are declared here rather than in Heap-X-Buffer in order to
    // reduce the number of virtual method invocations needed to access these
    // values, which is especially costly when coding small buffers.
    //
    final byte[] hb;  // Non-null only for heap buffers,缓存空间
    final int offset;
    boolean isReadOnly; 
     ByteBuffer(int mark, int pos, int lim, int cap,   // package-private
                 byte[] hb, int offset)
    {
        super(mark, pos, lim, cap);
        this.hb = hb;
        this.offset = offset;
    }
}

再来看
class HeapByteBuffer
    extends ByteBuffer
{
    HeapByteBuffer(byte[] buf, int off, int len) { // package-private
        super(-1, off, off + len, buf.length, buf, 0);
        /*
        hb = buf;
        offset = 0;
        */
    }
}

来看压缩函数
/*
 * compact操作用于当
 *  while (in.read(buf) >= 0 || buf.position != 0) {
 *     buf.flip();
 *     out.write(buf);
 *     buf.compact();    // In case of partial write
 *    }
 * 当out发送数据,即读取buf的数据,write方法可能只发送了部分数据,buf里还有剩余,
 * 这时调用buf.compact()函数将position与limit之间的数据,copy到buf的0到limit-position,
 * 进行压缩(非实际以压缩,只是移动),
 * 以便下次 向写入缓存。
 */
public ByteBuffer compact() {
        //将position与limit之间的数据,copy到buf的0到limit-position
        System.arraycopy(hb, ix(position()), hb, ix(0), remaining());
	//重新定位position
        position(remaining());
	//重新赋值limit
        limit(capacity());
	//废弃标记位置
        discardMark();
        return this;
    }

在来看一下put函数
 public ByteBuffer putChar(char x) {
        //Char,占两字节
        Bits.putChar(this, ix(nextPutIndex(2)), x, bigEndian);
        return this;
    }

 public ByteBuffer putInt(int x) {
        //int占4个字节
        Bits.putInt(this, ix(nextPutIndex(4)), x, bigEndian);
        return this;
    }

我们,详看一下putInt
//Buffer
//判断是否有足够空间存放nb个字节,并返回position的原先位置,同时移动position
 final int nextPutIndex(int nb) {                    // package-private
        if (limit - position < nb)
            throw new BufferOverflowException();
        int p = position;
        position += nb;
        return p;
    }

//HeapByteBuffer
  //定位到缓存写开始的位置
  protected int ix(int i) {
        return i + offset;
    }

//Bits
将int值x,从bb的bi位置,写入
 static void putInt(ByteBuffer bb, int bi, int x, boolean bigEndian) {
        if (bigEndian)
            putIntB(bb, bi, x);
        else
            putIntL(bb, bi, x);
    }
    
    //由于int占4个字节,将int的每个字节,拆分放入缓存ByteBuffer中
    static void putIntL(ByteBuffer bb, int bi, int x) {
        bb._put(bi + 3, int3(x));
        bb._put(bi + 2, int2(x));
        bb._put(bi + 1, int1(x));
        bb._put(bi    , int0(x));
    }
    private static byte int3(int x) { return (byte)(x >> 24); }
    private static byte int2(int x) { return (byte)(x >> 16); }
    private static byte int1(int x) { return (byte)(x >>  8); }
    private static byte int0(int x) { return (byte)(x      ); }

 
从ByteBuffer bb的比位置获取int值
static int getIntL(ByteBuffer bb, int bi) {
        return makeInt(bb._get(bi + 3),
                       bb._get(bi + 2),
                       bb._get(bi + 1),
                       bb._get(bi    ));
 static private int makeInt(byte b3, byte b2, byte b1, byte b0) {
        return (((b3       ) << 24) |
                ((b2 & 0xff) << 16) |
                ((b1 & 0xff) <<  8) |
                ((b0 & 0xff)      ));
    }

从上面可以看出向缓存中写入占多字节的原始类型Char,int,float等时,
HeapByteBuffer,通过Bit将原始类型字节拆分存入到ByteBuffer的缓存中。


总结:
get*(int index)方法不改变mark,limit和capacity的值;put则回改变position的位置,put操作后position的位置为,put操作之前position+length(put 操作数);
mark操作会改变mark的值,reset操作,则是将position定位到mark;clear操作并不会清空缓冲空间,而是将position复位0,limit为capacity,mark为-1;remain操作返回的是可用的空间大小为capacity-position;如put后,超出缓冲区大小,则抛出BufferOverflowException异常。
compact操作一般在一下情况调用,当out发送数据,即读取buf的数据,write方法可能只发送了部分数据,buf里还有剩余,这时调用buf.compact()函数将position与limit之间的数据,copy到buf的0到limit-position,进行压缩(非实际以压缩,只是移动),以便下次 向写入缓存。当position与limit之间的数据为空时,则不改变原缓冲区,否则copy相应数据。HeapByteBuffer向缓存中写入占多字节的原始类型Char,int,float等时,HeapByteBuffer,通过Bit将原始类型字节拆分存入到ByteBuffer的缓存中。

下面用图来模仿相关操作:
初始化:



写数据:



mark:



再次写数据:



reset操作:





flip操作,左图为操作前,右图为操作后;



rewind操作,左图为操作前,右图为操作后;



clear操作,上图为操作前,下图为操作后;



compact操作,有数据的情况下,上图为操作前,下图为操作后;



compact操作,无数据的情况下,上图为操作前,下图为操作后;








  • 大小: 5.1 KB
  • 大小: 5.4 KB
  • 大小: 5 KB
  • 大小: 5 KB
  • 大小: 4.6 KB
  • 大小: 9.6 KB
  • 大小: 6.8 KB
  • 大小: 9.6 KB
  • 大小: 10.1 KB
  • 大小: 9.9 KB
3
0
分享到:
评论

相关推荐

    java NIO和java并发编程的书籍

    java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...

    深入理解Apache Mina (6)---- Java Nio ByteBuffer与Mina ByteBuffer的区别

    NULL 博文链接:https://chinaestone.iteye.com/blog/468138

    Java NIO详解及源码下载

    博客地址:http://blog.csdn.net/u010156024/article/details/44310709 欢迎访问。 代码中详细讲述了Java io流和nio流的用法,可以参考学习。

    JavaNIO chm帮助文档

    Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六)...

    java nio 包读取超大数据文件

    Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据文件Java nio 超大数据文件 超大数据...

    Java NIO英文高清原版

    Java NIO英文高清原版

    java NIO 中文版

    讲解了 JavaIO 与 JAVA NIO区别,JAVA NIO设计理念,以及JDK中java NIO中语法的使用

    Java NIO详解(学习资料)

    Java NIO详解

    Java NIO 中文 Java NIO 中文 Java NIO 中文文档

    Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...

    java NIO 视频教程

    Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。 Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,...

    JAVA NIO 按行读取大文件支持 GB级别-修正版

    设计思想: 每次通过nio读取字节到 fbb中 然后对fbb自己中的内容进行行判断即 10 回车 13 行号 0 文件结束 这样字节的判断,然后 返回行 如果 到达 fbb的结尾 还没有结束,就再通过nio读取一段字节,继续处理。 ...

    java nio 实现socket

    java nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socketjava nio 实现socket

    java nio中文版

    java NIO是 java New IO 的简称,在 jdk1.4 里提供的新 api 。 Sun 官方标榜的特性如下: – 为所有的原始类型提供 (Buffer) 缓存支持。 – 字符集编码解码解决方案。 – Channel :一个新的原始 I/O 抽象。 – 支持...

    Java NIO实战开发多人聊天室

    05-Java NIO-Channel-FileChannel详解(一).mp4 06-Java NIO-Channel-FileChannel详解(二).mp4 08-Java NIO-Channel-ServerSocketChannel.mp4 09-Java NIO-Channel-SocketChannel.mp4 10-Java NIO-Channel-...

    Java Nio selector例程

    java侧起server(NioUdpServer1.java),基于Java Nio的selector 阻塞等候,一个android app(NioUdpClient1文件夹)和一个java程序(UI.java)作为两个client分别向该server发数据,server收到后分别打印收到的消息...

    基于Java NIO实现五子棋游戏.zip

    基于Java NIO实现五子棋游戏.zip基于Java NIO实现五子棋游戏.zip 基于Java NIO实现五子棋游戏.zip基于Java NIO实现五子棋游戏.zip 基于Java NIO实现五子棋游戏.zip基于Java NIO实现五子棋游戏.zip 基于Java NIO实现...

    NIO(byteBuffer)按行读取文件

    使用nio byteBuffer 实现按行读取文件(大文件) 在window/linux/macOS上均测试通过 对于中文乱码也已处理成功 完整注释,可随需求更改 有问题请邮件:mly610865580@126.com

    java NIO技巧及原理

    java NIO技巧及原理解析,java IO原理,NIO框架分析,性能比较

    java NIO.zip

    java NIO.zip

    JavaNIO想详解1

    本文中的源代码可以在此处下载,下载链接为:http://115.com/file/cltlj10i#nio-src.zip本文简介: JDK 1.4 中引入的

Global site tag (gtag.js) - Google Analytics