Java I/O system (5)-buffer class

Source: Internet
Author: User
Tags class definition rewind
Introduction

In the Java IO system, a new IO system was introduced in the JDK1.4, which we often call NIO, and its main function is to improve speed. In this blog post, we detail the construction of NiO: Channels and buffers, and the core understands Bytebuffer because it is the only buffer that interacts directly with the channel. The author currently organized some blog for the interview are ultra-high frequency. You can click on the link: http://blog.csdn.net/u012403290 channel and Buffer

Channel refers to the real existence of resources, and the buffer is the medium of transportation resources. For example, when we drink water and time: It is the channel, and the Cup is the bumper. We do not drink water directly, usually we use a glass to put it in, and then drink it with a cup. Similarly, we do not directly manipulate the channel, but operate the buffer, through the buffer to operate the channel.
For NIO,JDK, there are 4 packages in the Java.nio package, the main buffer and buffer and buffer extensions, etc., in the Java.nio.channels package is mainly the description of the file channel. This blog post is mainly about further explanations of channels and buffers.
Channel (FileChannel), which we typically get in the old IO system, consists mainly of 3 classes: Fileinputstream,fileoutputstream and Randomaccessfile, for these 3 classes, In front of the two we can define 2 input channels and output channels. For the latter, based on the nature of the randomaccessfile, we can move anywhere in the file to get the right resources. and buffers, we generally need to create an object of the appropriate size ourselves.

Buffers with a buffer class implementation are as follows:
Bytebuffer
Charbuffer
DoubleBuffer
Floatbuffer
Intbuffer
Longbuffer
Shortbuffer
Where the direct interaction with the channel is Bytebuffer, because it is the direct surface of raw bytes.

The following code is the simplest to create 2 channels with a buffer:

Package Com.brickworkers.io.nio;

Import Java.io.FileInputStream;
Import java.io.FileNotFoundException;
Import Java.nio.ByteBuffer;
Import Java.nio.channels.FileChannel;

public class Channelandbuffertest {public

    static void Main (string[] args) throws FileNotFoundException {
        // Create an input channel
        filechannel in = new FileInputStream ("F:/java/io/in.txt"). Getchannel (),
                //Create an output channel out
                    = new FileInputStream ("F:/java/io/out.txt"). Getchannel ();

        Build a bumper
        bytebuffer bf = bytebuffer.allocate (1024);
    }

Bytebuffer Buffer Detailed

1. Class definition
The following is the class structure definition for Bytebuffer:

Public abstract class Bytebuffer
    extends Buffer
    implements Comparable<bytebuffer>
    }

It can be seen from above that Bytebuffer is implemented by inheritance of buffer, while it itself is an abstract class, and it implements the comparison interface, the two bytebuffer can be compared to size. We're not going to discuss anything else, and in the class definition we know about the core structure of the buffer, so let's take a look at the basic components of the buffer:

Public abstract class Buffer {

    /**
     * The characteristics of spliterators that traverse and split elements
     * MA intained in buffers.
     * *
    static final int spliterator_characteristics =
        spliterator.sized | spliterator.subsized | spliterator.ordered;

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

There are 4 important fields in buffer: ①mark represents the position of the current position, which means that when we call Mark, Mark points to where position is pointing. ②position represents the current operating position. In a well defined buffer, each time we read or write the data, the position moves accordingly, equivalent to the randomaccessfile of the previous posting introduction, the movement of the file pointer. ③limit represents a read-write boundary that represents all read or write completion when the position position equals limit; ④capacity represents the size of the buffer capacity defined.
In the later demo will show details of the 4 variables of the specific operation.

2. Constructor function
The following is the Bytebuffer's constructor source code:

    Bytebuffer (int mark, int pos, int lim, int cap,   //Package-private
                 byte[] HB, int offset)
    {
        super (Mark, PO S, Lim, cap);
        THIS.HB = HB;
        This.offset = offset;
    }

    Creates a new buffer with the given mark, position, limit, and capacity
    //
    bytebuffer (int mark, int pos, int Lim, int cap) {//package-private this
        (Mark, POS, Lim, cap, NULL, 0);
    }

After reading the constructor, we know that we cannot create the Bytebuffer object directly from the constructor because it is a private method of the packet hierarchy. So how do we get a buffer object, like many classes, Bytebuffer also creates objects from a static factory method, see the following method:

Object creates a static method 1 public
   static Bytebuffer allocatedirect (int capacity) {return
        new Directbytebuffer (capacity);
    }

//Object creation static Method 2 public
    static Bytebuffer allocate (int capacity) {
        if (capacity < 0)
            throw new IllegalArgumentException ();
        return new Heapbytebuffer (capacity, capacity);
    }
Object Create static Method 3 public
   static Bytebuffer wrap (byte[] array,
                                    int offset, int length)
    {
        try {
            return new Heapbytebuffer (array, offset, length);
        } catch (IllegalArgumentException x) {
            throw new indexoutofboundsexception ();
        }
    }
Object creates a static method 4 public
  static Bytebuffer wrap (byte[] array) {return
        wrap (array, 0, array.length);
    }

As can be seen from the Bytebuffer static factory approach: ① and ② are directly creating an empty, specified size of the new buffer. So what's the difference between the two? The Allocatedirect method is more efficient than the allocate method by consulting relevant data. ③ and ④ are easier to understand by wrapping a byte array into a bytebuffer buffer, but the ③ method can specify the exact location of the array of byte that needs to be wrapped, and it has an offset as an entry.

3. Core Method
① the method inherited from the buffer class:
1. Clear () Empty the buffer

    Public final Buffer Clear () {
        position = 0;
        Limit = capacity;
        Mark =-1;
        return this;
    }

From the source can be seen, not really clear the data, but changed the value of each parameter, in fact, is to restore the various pointers to the original state. Usually this method is used when reusing a buffer.

2, Hasremaining (): To determine whether the current buffer has available data

    Public Final Boolean hasremaining () {return
        position < limit;
    }

From the source can be seen, in fact, is to see the current operation of the position pointer does not coincide with the limit pointer. This method is mainly to judge when the data in the buffer is obtained.

3, Flip (): Used to reset the operation of the pointer position, structured buffer data, to ensure that the data between position and limit is valid

   Public final Buffer Flip () {
        limit = position;
        Position = 0;
        Mark =-1;
        return this;
    }

From the source can be seen, the equivalent of the buffer operation Reset, note that the reset is not empty, and, this operation will be the end of the valid data defined to the position of the current operation. Therefore, this method of error invocation may result in buffer invalidation, for example, if you position to 0 of the time call this method, then the effective data directly into 0.

4, Rewind (): Operation Pointer Reset. This method does not guarantee that the data between position and limit is valid, and does not accidentally erase the data, compared to the flip method.

   Public final Buffer Rewind () {
        position = 0;
        Mark =-1;
        return this;
    }

This method is generally applicable to the need to loop through a buffer, such as the first operation from the beginning to the end, the second came in need to call the Rewind method, and then start reading, or you can not read data.

5. Mark () marks the current position position

   Public final Buffer Mark () {
        mark = position;
        return this;
    }

This method is primarily used to mark the current operating position, for specific operations, such as the processing of data for all the odd digits in a buffer. Then we need to record the last operating position and mark it at this point.

6, Reset () The current operation pointer position point to mark's place

   Public final Buffer Reset () {
        int m = mark;
        if (M < 0)
            throw new Invalidmarkexception ();
        Position = m;
        return this;
    }

In general, if you use this method, the premise is that you have used the Mark method, or Mark's default is -1 position.

In fact, the method in the buffer is not only here. The following code contains all the methods described above:

Package Com.brickworkers.io.nio;
Import Java.io.FileInputStream;
Import Java.io.FileOutputStream;
Import java.io.IOException;
Import Java.nio.ByteBuffer;

Import Java.nio.channels.FileChannel; public class Channelandbuffertest {public static void main (string[] args) throws IOException {//Establish 2 channels, respectively, is the loss Enter and output filechannel in = new FileInputStream ("F:/java/io/bw.txt"). Getchannel (), out = new Fileout


        Putstream ("F:/java/io/bw.txt"). Getchannel ();

        Establish a universal buffer bytebuffer BF = bytebuffer.allocate (64);

        Get this buffer to wrap a value bf.put ("Brickworkers". GetBytes ());
        Note that here the position of the position pointer has changed, the operation pointer must be moved to the beginning, the Filp method is recommended, because the brickwork byte number is less than 64, avoid unnecessary overhead bf.flip ();
        Give the buffer to the output channel and write the value to the file Out.write (BF);
        Out.close ();
        After writing, the BF is emptied to store the value obtained from the input channel bf.clear ();
        The input channel puts the value to the buffer In.read (BF);
        In.close ();
        Start with the original position of the position pointer, which can be either flip or rewind.
    Bf.flip ();    We're going to swap the adjacent characters for the position while (bf.hasremaining ()) {//Mark first with Mark, indicating the current operation position Bf.mark ();
            byte ch1 = Bf.get ();
            byte CH2 = Bf.get (); When this is done, the position pointer has moved 2 bytes backwards.
            The position pointer must be moved to the Swap object before Bf.reset ().
        Position Exchange Bf.put (CH2). put (CH1);
        //reset position, because the above substitution operation has ended, so either the Filp method can be used, or the rewind method can be used Bf.flip ();
        while (Bf.hasremaining ()) {System.out.print ((char) bf.get ());

 ////Output Result://RBCIWKROEKSR//

However, there is a big problem with the above code, which may throw a java.nio.BufferUnderflowException error because the string you write is odd or even. If the even pass two times of Get (), in fact the position pointer has exceeded the limit. So in fact, the hasremaining () method in the first while of the above code is best to use this: remaining () > second, the judgment will be more reliable, meaning that when the last less than 2, the last letter is not replaced. You can try it on your own.

② creates an appropriate byte buffer view that can be used as a buffer for various basic data types. In fact, to get a more advanced buffer, such as ascharbuffer,asintbuffer,asdoublebuffer and so on. However, the direct interaction with the channel must be bytebuffer.
In the above demo use, we are using a while loop output characters, but we can also use Ascharbuffer direct bytebuffer out of the Charbuffer, you can replace the last while loop of the code above:

System.out.println (Bf.ascharbuffer ());

But note that there is a good chance that there will be garbled. The buffer bytebuffer is stored in bytes, if it is to be converted to a character, encoded when it is entered, or encoded at the time of output. We typically use a package java.nio.charset in NIO to specify the encoding, such as the following code:

Charbuffer cb = Charset.forname ("UTF-8"). Decode (BF);

We can then convert the Bytebuffer into Charbuffer by encoding it.

The

② Read method that reads data from the buffer, the Get method, and the corresponding data. A full byte array can be read, or an offset byte array exists. Even the getchar,getlong,getdouble and other methods. Storage method, storing the data where the position pointer points. The data for the entire buffer can be stored, or an offset byte array exists. Even the putchar,putlong,putdouble. In fact, this is equivalent to reading and writing in Randomaccessfile. Please refer to the following methods:

Package Com.brickworkers.io.nio;
Import Java.io.FileInputStream;
Import Java.io.FileOutputStream;
Import java.io.IOException;
Import Java.nio.ByteBuffer;
Import Java.nio.CharBuffer;
Import Java.nio.channels.FileChannel;

Import Java.nio.charset.Charset; public class Test {public static void main (string[] args) throws IOException {//To establish 2 channels, respectively, input and output Fil Echannel in = new FileInputStream ("F:/java/io/bw.txt"). Getchannel (), out = new FileOutputStream ("F:/ja


        Va/io/bw.txt "). Getchannel ();

        Establish a universal buffer bytebuffer BF = bytebuffer.allocate (1024);
        A byte bf.put ((Byte) ' a ') is stored first;
        Depositing a char Bf.putchar ((char) ' B ');
        Depositing a double bf.putdouble (3.1415926D);
        Deposited in a long bf.putlong (14L);

        deposited in an int bf.putint (13);
        Get the data sorted first and use the Flip method.
        Bf.flip ();

        The data in the buffer is transported into the output channel out.write (BF);
        First empty buffer bf.clear ();
       In.read (BF); Bf.flip ();
        Next we read the data/read a byte System.out.println (Bf.get ());
        Reads a char System.out.println (Bf.getchar ());
        Reads a double System.out.println (bf.getdouble ());
        Reads a long System.out.println (Bf.getlong ());


    Reads an int System.out.println (Bf.getint ()); ///Output results://97//b//3.1415926//14//13///

Some of the small partners are very strange, why I entered the byte is a, how to become 97. Because in ASCII code, a is 97.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.