• Java Buffer


    1.1 NIO Buffers - Class java.nio.Buffer

    NIO data transfer is through the so-called buffers implemented in java.nio.Buffer class. A Buffer is similar to an array, except that it's implemented much more efficiently by closely coupled with the underlying OS.A Buffer is a contiguous, linear storage. Similar to an array, a Buffer has a fixed capacity.

    The Buffer class for each of the primitibe types(except boolean), as shown in the above diagram. The abstarct superclass java.nio.Buffer provides the common properties  and some common operatons of all buffers.

    Buffer has a capacitypositionlimit, and an optional mark:

    • The capacity must be specified when the Buffer is constructed and cannot be changed (similar to an array). You can retrieve it via method capacity().
    • The limit specifies the current occupancy. In other word, the buffer contains valid data in the range 0 to limit-1. You can retrieve the current limit via method limit() or set the limit via methodlimit(int newLimit). Limit shall not be greater than capacity.
    • Unlike array, there is a so-called position (or cursor) in a Buffer that indicates where the next piece of data is to be read or written. You can retrieve the current position via method position() or change the current position via method position(int newPosition). Position shall not be greater than the limit.
    • mark provide a positional marker. You can mark the current position via the method mark().

    Data Transfer (Get/Put):

    Each of the primitive buffers provides a set of get() and put() methods to read/write an element or a array of elements from/to the buffer. The position increases by the number of elements transferred. For example, the IntBuffer provides:

    View Code

    ByteBuffer is special. It provides additional getXxx()/putXxx() methods to parse raw bytes into other primitive types. It also can be used as the sources and targets of I/O operations, which will be explained later in channel I/O.

    View Code

    Mark and Reset: 

    You can use mark() method to mark the current position. Invoking reset() sets the position to the previously-marked position. The mark may or may not be set. If the mark is not set, invoking reset() triggers an InvalidMarkException. If the mark is set, it should never be greater than the position (because the mark() marks the current position and position advances). The mark will be discarded when the position or the limit is adjusted to a value smaller than the mark. Hence, 0 ≤ mark ≤ position ≤ limit ≤ capacity.

    Clear, Flip and Rewind: 

    • clear(): sets the position to 0, limit to the capacity, and discards mark. It prepares the buffer for input.
    • flip(): sets the limit to the current positionposition to 0, and discard mark. Buffer populated and ready for output.
    • rewind(): set the position to 0, and discard mark. It prepares the buffer for re-read.

    Creating a Buffer: There are 3 ways to create a buffer:

    1. via method allocate(int capacity), which allocates a new buffer, sets position to 0 and limit to capacity, and clear the mark.
    2. wrap an existing array into buffer via wrap(type[] array, int offset, int length) or wrap(type[] array) method.
    3. by creating a view of an existing ByteBuffer (to be discussed later). 

    Slicing and data sharing:

    The slice() method creates sub-buffer from an existing buffer. That is it creates a new buffer sharing a portion of the original buffer.

    We can see a example:

    View Code

    Then we alter elements in the buffer(two buffers and the sub-buffers share the same underlying data array).

    Here is the ouput:

    before alter sub-buffer:0 1 2 3 4 5 6 7 8 9 
    alter elements in sub buffer.
    After altering sub buffer0 1 2 33 44 55 66 7 8 9

    Read-only buffers

    Read-only buffers means only read operation allowed. We can turn any regular buffer into a read-only buffer by calling its asReadOnlyBuffer() method, which returns a new buffer that is identical to the first (and shares data with it), but is read-only. But we can not turn an read-only buffer to writable buffer. 

    Direct and in Direct buffer

    To see the difference between these two buffer, please see Analysis about different methods for reading and writing file in Java language

    Memory-mapped file I/O

    Memory-mapped file I/O can read and write file more fast than regular stream or channel based I/O.

    Memory-mapped file I/O is accomplished by causing the data in a file to magically appear as the contents of a memory array. For it provide access to the facility that OS implement FS by mapping portions of a file into portions of memory, doing so on demand. 

    Mapping a file into memory example:

        static void MappingFileMem() throws IOException{
            String inFileStr = "/users/wsy/Documents/job/kimchi_v2.pdf";
            String outFileStr = "./kimchi_v2.pdf";
            long startTime, elapsedTime; // for speed benchmarking
            int bufferSizeKB = 4;
            int bufferSize = bufferSizeKB * 1024;
            FileInputStream input = new FileInputStream(inFileStr);
            FileChannel channel = input.getChannel();
    
            MappedByteBuffer mbb = channel.map(FileChannel.MapMode.READ_WRITE, 0, 1024);
        }
    View Code

    Scattering and gathering

    Scatter/gather I/O is a method of reading and writing that uses multiple buffers, rather than a single buffer. A scatter read reads data into a array of buffers rather than a single buffer. A gathering write writes data from a array of buffers rather than a single buffer.

    Applications of scatter/gather:

    Scatter/gather I/O is useful for dividing a piece of data into sections. For example, we can write a networking app that uses message objects, and each messages divided into a fixed-length header and body We can create 2 buffers, one for the header, and other for the body.When we put these 2 in an array and read data into them by scattering read, then the header and body will be neatly divided into 2 buffers. The scatter read will automatically find the first with room in it. After the previous filled, it movs to the next one.

    • long read( ByteBuffer[] dsts );
    • long read( ByteBuffer[] dsts, int offset, int length );

    Gathering writes is like the Scattering reads.

  • 相关阅读:
    高性能MySQL笔记(第十一章 可扩展的MySQL)01
    高性能MySQL笔记(第十章 复制)02
    高性能MySQL笔记(第十章 复制)01
    高性能MySQL笔记(第六章 查询性能优化) 02
    高性能MySQL笔记(一个奇怪的问题)
    高性能MySQL笔记(第六章 查询性能优化) 01
    高性能MySQL笔记(第五章 创建高性能的索引) 02
    高性能MySQL笔记(第五章 创建高性能的索引) 01
    [Luogu] P1438 无聊的数列 | 线段树简单题
    [UCF HSPT 2021] Sharon’s Sausages | 思维 暴力
  • 原文地址:https://www.cnblogs.com/wenwangt/p/5149241.html
Copyright © 2020-2023  润新知