zoukankan      html  css  js  c++  java
  • ByteBuffer使用实例

      ByteBuffer作为JDK的字节流处理对象,这里举个小例子说明下用法,直接上代码:

    package com.wlf.netty.nettyserver;
    
    import org.junit.Assert;
    import org.junit.Test;
    
    import java.nio.ByteBuffer;
    
    public class ByteBufferTest {
    
        @Test
        public void byteBufferTest() {
    
            // 写入消息体
            ByteBuffer byteBuffer = ByteBuffer.allocate(10);
            byteBuffer.putInt(0xabef0101);
            byteBuffer.putInt(1024); // 今天过节
            byteBuffer.put((byte) 1);
            byteBuffer.put((byte) 0);
    
            // 读取消息头,因为写完后position已经到10了,所以需要先反转为0,再从头读取
            byteBuffer.flip();
            printDelimiter(byteBuffer);
    
            // 读取length
            printLength(byteBuffer);
    
            // 继续读取剩下数据
            byteBuffer.get();
            byteBuffer.get();
            printByteBuffer(byteBuffer);
    
            // 我再反转一下,我还可以从头开始读
            byteBuffer.flip();
            printDelimiter(byteBuffer);
    
            // clear清空一下,再从头开始读
            byteBuffer.clear();
            printDelimiter(byteBuffer);
    
            // rewind重绕一下
            byteBuffer.rewind();
            printDelimiter(byteBuffer);
    
            // mark标记一下
            byteBuffer.mark();
    
            // 再读取length
            printLength(byteBuffer);
    
            // reset重置,回到读取delimiter的地方
            byteBuffer.reset();
            printByteBuffer(byteBuffer);
        }
    
        private void printDelimiter(ByteBuffer buf) {
            int newDelimiter = buf.getInt();
            System.out.printf("delimeter: %s
    ", Integer.toHexString(newDelimiter));
            printByteBuffer(buf);
        }
    
        private void printLength(ByteBuffer buf) {
            int length = buf.getInt();
            System.out.printf("length: %d
    ", length);
            printByteBuffer(buf);
        }
    
        private void printByteBuffer(ByteBuffer buf) {
            System.out.printf("position: %d, limit: %d, capacity: %d
    ", buf.position(), buf.limit(), buf.capacity());
        }
    }

      输出结果:

    delimeter: abef0101
    position: 4, limit: 10, capacity: 10
    length: 1024
    position: 8, limit: 10, capacity: 10
    position: 10, limit: 10, capacity: 10
    delimeter: abef0101
    position: 4, limit: 10, capacity: 10
    delimeter: abef0101
    position: 4, limit: 10, capacity: 10
    delimeter: abef0101
    position: 4, limit: 10, capacity: 10
    length: 1024
    position: 8, limit: 10, capacity: 10
    position: 4, limit: 10, capacity: 10
    
    Process finished with exit code 0

       ByteBuffer的索引是唯一的。像上面的例子,初始索引是0,写完索引值为9,为了读取写入的值,我们再重新设置索引为0(调用flip方法)。ByteBuffer有4个索引值,分别是:

      mask:就是你标记的索引,标记唯一的作用是调用reset重置回到过去

      position:当前位置的索引,mask标记任何时候都不会大于position,因为你必须先读到当前位置之后,才能标记该位置;同时position也不能超过limit限制

      limit:第一个不应该读取或写入的元素的索引,也就是读写禁地,默认是最大容量,如果你设置该值,那么理所让然它不能超过最大容量capacity

      capacity:这个就不解释了

      它们的大小关系始终是:

      mask <= position <= limit <= capacity

      我们上面的例子中就是capacity=limit。

      初始索引:

      +-----------------------------------------------------+

           /                            bytes                              /

           +-----------------------------------------------------+

           /                            10                                  /

      0=position                                               10=limit=capacity

      我们写入delimiter之后:

      +----------------+------------------------------------+

           /      delimiter /     other  bytes                       /

           +----------------+------------------------------------+

           /             4     /          6                                    /

       0        4=position                                     10=limit=capacity

      

      至于反转flip如何切换读写模式、reset如何重置标记、clear清除如何重新设置索引值为0、rewind重绕如何让你重新读取,都不会动内容,所以你会看到上面不管怎么折腾我们都可以重复取出delimiter、length的值。看下源码就一清二楚了,无非就是对上面4个索引值进行赋值而已:

        /**
         * Resets this buffer's position to the previously-marked position.
         *
         * <p> Invoking this method neither changes nor discards the mark's
         * value. </p>
         *
         * @return  This buffer
         *
         * @throws  InvalidMarkException
         *          If the mark has not been set
         */
        public final Buffer reset() {
            int m = mark;
            if (m < 0)
                throw new InvalidMarkException();
            position = m;
            return this;
        }
    
        /**
         * Clears this buffer.  The position is set to zero, the limit is set to
         * the capacity, and the mark is discarded.
         *
         * <p> Invoke this method before using a sequence of channel-read or
         * <i>put</i> operations to fill this buffer.  For example:
         *
         * <blockquote><pre>
         * buf.clear();     // Prepare buffer for reading
         * in.read(buf);    // Read data</pre></blockquote>
         *
         * <p> This method does not actually erase the data in the buffer, but it
         * is named as if it did because it will most often be used in situations
         * in which that might as well be the case. </p>
         *
         * @return  This buffer
         */
        public final Buffer clear() {
            position = 0;
            limit = capacity;
            mark = -1;
            return this;
        }
    
        /**
         * Flips this buffer.  The limit is set to the current position and then
         * the position is set to zero.  If the mark is defined then it is
         * discarded.
         *
         * <p> After a sequence of channel-read or <i>put</i> operations, invoke
         * this method to prepare for a sequence of channel-write or relative
         * <i>get</i> operations.  For example:
         *
         * <blockquote><pre>
         * buf.put(magic);    // Prepend header
         * in.read(buf);      // Read data into rest of buffer
         * buf.flip();        // Flip buffer
         * out.write(buf);    // Write header + data to channel</pre></blockquote>
         *
         * <p> This method is often used in conjunction with the {@link
         * java.nio.ByteBuffer#compact compact} method when transferring data from
         * one place to another.  </p>
         *
         * @return  This buffer
         */
        public final Buffer flip() {
            limit = position;
            position = 0;
            mark = -1;
            return this;
        }
    
        /**
         * Rewinds this buffer.  The position is set to zero and the mark is
         * discarded.
         *
         * <p> Invoke this method before a sequence of channel-write or <i>get</i>
         * operations, assuming that the limit has already been set
         * appropriately.  For example:
         *
         * <blockquote><pre>
         * out.write(buf);    // Write remaining data
         * buf.rewind();      // Rewind buffer
         * buf.get(array);    // Copy data into array</pre></blockquote>
         *
         * @return  This buffer
         */
        public final Buffer rewind() {
            position = 0;
            mark = -1;
            return this;
        }
  • 相关阅读:
    看K线学炒股(8.10)
    看K线学炒股(8.9)
    看K线学炒股(8.5)
    看K线学炒股(0803)
    看K线学炒股(7.29)
    看K线学炒股(7.21)
    看K线学炒股(2021.07.20)
    看K线学炒股
    说说英力特这只股票
    matlab里的数据转换到Python中去的一个问题
  • 原文地址:https://www.cnblogs.com/wuxun1997/p/11735826.html
Copyright © 2011-2022 走看看