Java mappedByteBuffer和flip()和position()

Java mappedByteBuffer和flip()和position(),java,buffer,nio,Java,Buffer,Nio,我对java.nio.Buffer有一些问题。基本上,我的问题是,是否总是需要调用flip()来在读和写之间切换,或者只需要调用来实现缓慢的I/O,例如,在先写后读的情况下,以确保数据在读取之前完全写入。我特别要问的是mappedByteBuffer。看起来,如果文件存在并且大小与我所知道的相同,我可以使用position(int newPosition)调用导航到文件的任何部分,并执行读或写操作,即基本上使用缓冲区作为内存块,忘记标记或限制的概念。这是真的吗 考虑下面的例子。如果我有一个包含整

我对
java.nio.Buffer
有一些问题。基本上,我的问题是,是否总是需要调用
flip()
来在读和写之间切换,或者只需要调用来实现缓慢的I/O,例如,在先写后读的情况下,以确保数据在读取之前完全写入。我特别要问的是mappedByteBuffer。看起来,如果文件存在并且大小与我所知道的相同,我可以使用
position(int newPosition)
调用导航到文件的任何部分,并执行读或写操作,即基本上使用缓冲区作为内存块,忘记标记或限制的概念。这是真的吗

考虑下面的例子。如果我有一个包含整数1的文件,那么从一开始就是2,我似乎可以将另一个整数3放在位置0,倒带并从缓冲区读取3和2。这个限制不应该像在正常的非mmap缓冲区中那样阻止我执行第二个getInt吗?我什么时候需要调用flip()在mappedByteBuffer的写入和读取之间切换?谢谢

final int FILESIZE = 1024;

RandomAccessFile fileHandle;
    FileChannel fileChannel;
    File testFile = new File("c:/temp/testbbrw.dat");
    fileHandle = new RandomAccessFile(testFile, "rw");

    fileChannel = fileHandle.getChannel();
    MappedByteBuffer mbb = fileChannel.map(FileChannel.MapMode.READ_WRITE, 0, FILESIZE);

    int pos, data;

    mbb.position(0);
    mbb.putInt(3);

    mbb.position(0);
    data=mbb.getInt();  //I get 3
    data=mbb.getInt();  //I get 2, which was written to the file before this program runs

    mbb.force();
    fileHandle.close();

这就是Buffer.flip的作用

347    public final Buffer flip() {
348        limit = position;
349        position = 0;
350        mark = -1;
351        return this;
352    }
它正在准备缓冲区,以便缓冲区上的下一次读取操作从位置0开始,在当前限制结束。意味着你告诉它,你已经完成了对缓冲区的更改,并准备将其移动或复制到其他地方(这意味着读取它)

我的问题首先是,是否总是需要flip()调用来在读和写之间切换,还是仅在I/O速度较慢时才需要,例如,在先写后读的情况下,以确保数据在读取之前完全写入

  • 任何描述的
    缓冲区
    都是在一种状态下开始的,在这种状态下,您可以读入或放入缓冲区,这是相同的
  • flip()
    将它置于一种状态,您可以从中写入,也可以从中获取,这是相同的
  • 尽管它的名字(非常愚蠢),
    flip()
    不是
    flip()
    的反义词。它唯一的反面是
    compact()
    clear()
  • 为了清楚起见,我发现最好总是将
    缓冲区保持在可读状态,并且只在需要时将其翻转到可写状态,然后立即将其恢复为可读状态

    这是用于I/O的


    如果你只是做
    get()
    put()
    我不确定我会使用
    flip()
    ,因为这是一个
    MappedByteBuffer
    我肯定不会调用
    clear()
    compact()
    ,这两种方法都会对文件造成可怕的影响,而且也排除了使用
    flip()的可能性

    与典型的循环有限缓冲区相比,Java中
    缓冲区的设计既混乱又违反直觉。更糟糕的是,文档中的术语选择不当,再加上读/写和put/get术语的使用模棱两可,前者指的是外部操作(通常通过
    通道
    使用a
    缓冲区
    ,后者指的是a
    缓冲区提供的操作

    Java缓冲区 创建时,新缓冲区为“空”,准备填充。构造函数中可能会立即提供一些内容,但它仍处于“填充”状态

    flip()
    方法将缓冲区的逻辑状态从填充状态“翻转”为清空状态。相当愚蠢的是,
    flip()
    不会自动反转,即使在普通英语中它通常描述逻辑上可逆的动作。事实上,查看代码,在不进行干预的情况下调用两次
    clear
    compact
    会将缓冲区设置为无效状态,导致其他方法返回无意义。[1]

    clear()
    compact()
    方法是
    flip()
    的逻辑逆,将缓冲区恢复为“填充”状态,前者同时清空缓冲区,后者保留剩余内容

    一般建议使用try/finally将任何给定的缓冲区始终保持在一致状态;例如:

    ByteBuffer wrap(ByteBuffer src, ByteBuffer tgt) {
        // assume buffers are *always* kept in the "filling" state
        try {
            src.flip(); // change `src` to "emptying"; assume tgt already filling
            // transfer some or all of `src` to `tgt`
            }
        finally {
            if(src.remaining()) { src.compact(); } // revert `src` to "filling" without discarding remaining data
            else                { src.clear();   } // compact() is (usually) less efficient than clearing
            }
    
      511       final int nextPutIndex() {                          // package-private
      512           if (position >= limit)
      513               throw new BufferOverflowException();
      514           return position++;
      515       }
      516   
      517       final int nextPutIndex(int nb) {                    // package-private
      518           if (limit - position < nb)
      519               throw new BufferOverflowException();
      520           int p = position;
      521           position += nb;
      522           return p;
      523       }
      524   
      525       /**
      526        * Checks the given index against the limit, throwing an {@link
      527        * IndexOutOfBoundsException} if it is not smaller than the limit
      528        * or is smaller than zero.
      529        */
      530       final int checkIndex(int i) {                       // package-private
      531           if ((i < 0) || (i >= limit))
      532               throw new IndexOutOfBoundsException();
      533           return i;
      534       }
    
    典型的有限循环缓冲器 Java缓冲区最不直观的原因是,大多数循环缓冲区实现都具有并发读/写能力,因此它们保持三个值,
    容量
    (如果语言允许,最后一个值通常从支持数组推断)它们只允许将值包装起来。
    head
    是读取数据的地方,
    tail
    是写入数据的地方。当到达基础数组的末尾时,head/tail的值被简单地设置为零(即它循环)

    head==tail
    时,缓冲区为空。当
    inc(tail)==head
    时,缓冲区已满,当前内容长度由
    head=limit)得出
    513抛出新的BufferOverflowException();
    514返回位置++;
    515       }
    516
    517最终int nextPutIndex(int nb){//包专用
    518如果(极限位置=极限))
    532抛出新IndexOutOfBoundsException();
    533返回i;
    534       }
    
    在运行程序之前,文件中是否可能有多个2?很抱歉,应首先阅读:)您使用覆盖文件中的1