首页 > 其他 > 详细

ByteBuffer中的write方法,read方法

时间:2020-06-04 09:22:30      阅读:105      评论:0      收藏:0      [点我收藏+]

我去查看read方法的底层源码:(bb:bytebuffer)

发现read方法的实现:bb.flip()、dst.put(bb)  写入缓冲区

write方法的实现:  bb.put(src)  |bb.flip()  (bb.put(src):写入文件需要的缓冲区)

注意put()方法中参数的不同和使用flip()方法的顺序,

使用read方法,先调用flip()方法,再将数据送入缓冲区

使用write方法,将数据写到写入文件的缓冲区,在调用flip()方法使position位置变为0,然后可以继续put,继续flip()保证每次都是从0位置开始取数据,并且每一次limit都是新放入buffer中的数据的长度,确保数据不会有错误

表明read方法和write方法都是使用put来完成的,那为什么两个方法不同呢,主要在于flip()方法

public ByteBuffer put(byte x) {

        hb[ix(nextPutIndex())] = x;
        return this;



    }

    public ByteBuffer put(int i, byte x) {

        hb[ix(checkIndex(i))] = x;
        return this;



    }

    public ByteBuffer put(byte[] src, int offset, int length) {

        Objects.checkFromIndexSize(offset, length, src.length);
        int pos = position();
        if (length > limit() - pos)
            throw new BufferOverflowException();
        System.arraycopy(src, offset, hb, ix(pos), length);//  final byte[] hb;  // Non-null only for heap buffers  这是hb的解释:不空。堆缓冲
position(pos + length); return this; }
    public byte get() {
        return hb[ix(nextGetIndex())];
    }

    public byte get(int i) {
        return hb[ix(checkIndex(i))];
    }







    public ByteBuffer get(byte[] dst, int offset, int length) {
        Objects.checkFromIndexSize(offset, length, dst.length);
        int pos = position();
        if (length > limit() - pos)
            throw new BufferUnderflowException();
        System.arraycopy(hb, ix(pos), dst, offset, length);
        position(pos + length);
        return this;
    }

    public ByteBuffer get(int index, byte[] dst, int offset, int length) {
        Objects.checkFromIndexSize(index, length, limit());
        Objects.checkFromIndexSize(offset, length, dst.length);
        System.arraycopy(hb, ix(index), dst, offset, length);
        return this;
    }

 put方法的实现:  System.arraycopy(src, offset, hb, ix(pos), length);

get方法的实现:  System.arraycopy(hb, ix(pos), dst, offset, length);

@HotSpotIntrinsicCandidate
    public static native void arraycopy(Object src,  int  srcPos,
                                        Object dest, int destPos,
                                        int length);

 
从指定的源数组复制一个数组,从
      *指定位置,到目标数组的指定位置。
      *从源复制数组组件的子序列
      * {@code src}引用到目标数组的数组
      *由{@code dest}引用。 复制的组件数为
      *等于{@code length}参数。 的组件
      *位置{@code srcPos}至
      *将源数组中的{@code srcPos + length-1}复制到
      *位置{@code destPos}至
      *分别为目的地的{@code destPos + length-1}
      *数组。
 
 
 

总体来说就是将src数组复制到dest数组,这个就是get方法和put方法,都是将src“表示的文件”复制到dest“表示的文件”

所以put方法和get方法可以看作是同一类方法,只不过参数位置恰好相反

而write方法和read方法是用put方法实现的,但是put()方法中的参数也是正好相反,这样就能理解write和read对文件的读取了。

回过头:我们分析flip方法:

英文api:

public Buffer flip()
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.

After a sequence of channel-read or put operations, invoke this method to prepare for a sequence of channel-write or relative get operations. For example:

 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

This method is often used in conjunction with the compact method when transferring data from one place to another.

Returns:
This buffer

 

调用flip方法之后:

position:表示当前指针位置变为0

limit:可以理解为指针能读取buffer中的数据的最大位置的下一个位置

注意初始化limit为capacity(最大容量)

我们使用put方法会覆盖之前的数据,不管是哪个方法都是从position位置开始的,需要注意position的变化

 

 

 

 

 

 

 

ByteBuffer中的write方法,read方法

原文:https://www.cnblogs.com/guosai1500581464/p/13041187.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!