We usually often the files are read operations, such as using FileInputStream read operation, the efficiency is very low. For this purpose we can use the byte stream buffer BufferedInputStream to operate, the efficiency of reading will be greatly improved. In this we introduce the principles of how to use BufferedInputStream and analyze their work.
I. Introduction to use:
1.1 Definitions:
BufferedInputStream Advanced Stream is not directly manipulate files, only low-flow can be directly connected to the file, so need a lower stream socket, such as:
FileInputStream fis = new FileInputStream("test.txt");
BufferedInputStream bis = new BufferedInputStream(fis);
1.2 to read the file:
When reading, we generally use the read () method reads a cycle, such as to the end of the file is read, the read () method returns -1, for example:
int len = -1 ;
while ((len = bis.read ())! = - 1 ) {
System.out.println (only);
}
By way loop to read, you can read a file is completed.
Second principle analysis:
From the foregoing understanding of the use BufferedInputStream, and that is how it works? Here will come to understand the principle of source code analysis by the BufferedInputStream.
2.1 Firstly, properties, and constructors under BufferedInputStream of:
Properties are as follows:
// The default buffer size 8K Private static int DEFAULT_BUFFER_SIZE = 8192 ; / * maximum buffer size Integer.MAX_VALUE - 8, 8 is reduced due to the virtual machine reserves some header information in the array * / Private static int MAX_BUFFER_SIZE = Integer. MAX_VALUE -. 8 ; // buffer byte array definition data stored in the protected volatile byte buf []; // atoms properties updater, to ensure atomic updates buf Private static Final AtomicReferenceFieldUpdater <BufferedInputStream, byte []> = bufUpdater AtomicReferenceFieldUpdater .newUpdater (BufferedInputStream. class , byte . [] class , "buf" ); // buf byte array of the actual data size protected int COUNT; // position to start reading of protected int POS; // record the reading start position of the last protected int markpos = -1 ; // maximum permitted advance is read protected int marklimit;
Constructor as follows:
// to InputStream as parameters, the default buffer size 8K public BufferedInputStream (InputStream in) { the this (in, DEFAULT_BUFFER_SIZE); } // custom buffer size public BufferedInputStream (InputStream in, int size) { Super (in); IF (size <= 0 ) { the throw new new an IllegalArgumentException ( "Buffer size <= 0" ); } buf = new new byte [size]; }
2.2 Analysis Methods:
2.2.1.read () method of analysis:
// no parameter read () method public the synchronized int read () throws IOException { // if the reading start position is equal to or greater than the actual size of the buffer IF (POS> = COUNT) { // is filled buffer fill () ; // after filling, the reading position is equal to or greater than the actual size of the buffer, the read, return -1 IF (POS> = COUNT) return -1 ; } // return the first byte in the buffer return getBufIfOpen () [POS ++] & 0xFF ; }
2.2.2.read1 (byte [] b, int off, int len) Analysis Method:
This method of byte array can be customized, and the position to start reading and the actual reading of the length of the source as follows:
Private int Read1 ( byte [] B, int OFF, int len) throws IOException { // size readable int Avail = COUNT - POS; // if the size is less than or equal to read 0 IF (Avail <= 0 ) { // if len is greater than or equal to the buffer size and the mark position is less than 0, then the reading of the length of the given IF (len> = getBufIfOpen (). && markpos length <0 ) { return getInIfOpen (). read (B, OFF, len); } // if otherwise, the default size read Fill (); Avail = COUNT - POS; // If the size is less than or equal to read, the read, return -1 IF (avail <= 0) return -1 ; } // take a smaller value between the avail and len int CNT = (avail <len ?) Avail: len; // the byte array buffer starting from the position pos, length b is copied to the start byte array off for the content of cnt System.arraycopy (getBufIfOpen (), pos, b, off, CNT); // reading position increases CNT POS + = CNT; // returns the length of the read return CNT; }
2.2.3.read (byte b [], int off, int len) Analysis Method:
public the synchronized int Read ( byte B [], int OFF, int len) throws IOException { // check whether the flow off getBufIfOpen (); // the Check for Stream Closed // by "|" operation to ensure that off, len is greater than or equal to 0 , b.length greater than or equal to len + OFF IF ((OFF | len | (OFF + len) | (to b.length - (OFF + len))) <0 ) { the throw new new an IndexOutOfBoundsException (); } the else IF (len 0 == ) { return 0 ; } int= 0 n- ; // infinite loop, as long as the remaining contents to meet the length len, it can be read to ensure that each length len for (;;) { // read length len bytes int Nread Read1 = (B, + n-OFF, len - n-); IF (Nread <= 0 ) return ? (n-== 0) Nread: n-; // because the length of a byte array buffer 8192, assuming 800 len, is read 10 times Thereafter, the remaining buffer length is 192 bytes, the length of the first reading is 192, i.e. n-192, in this case, does not return to cycle again the cycle again, the first buffer is filled, then after reading the remaining 608 to 800 is read, the length 800 is returned. n-+ = Nread; IF (n-> = len) return n-; // IF Closed But Not Available bytes NO, return INPUT = the InputStream in; // if the input stream to the available buffer size is less than or equal to 0, then n returns IF (! INPUT = null && input.available () <= 0 ) return n; } }
2.2.4.fill () method of analysis:
fill () method is used to read data and fill the buffer.
Private void Fill () throws IOException { // check whether the flow Close byte [] = Buffer getBufIfOpen (); // Analyzing marker position is less than 0 IF (markpos <0 ) // set to position 0, i.e., start position pos = 0; / * NO Mark: the throw Away The buffer * / // If the position is greater than or equal to the buffer size, the following logical processing press the else IF (POS> = buffer.length) / * NO Room left in buffer * / IF (markpos> 0) { / * CAN Early Part of the throw Away The Buffer * / int SZ = POS - markpos; System.arraycopy(buffer, markpos, buffer, 0, sz); pos = sz; markpos = 0; } else if (buffer.length >= marklimit) { markpos = -1; /* buffer got too big, invalidate mark */ pos = 0; /* drop buffer contents */ } else if (buffer.length >= MAX_BUFFER_SIZE) { throw new OutOfMemoryError("Required array size too large"); } else { /* grow buffer */ int nsz = (pos <= MAX_BUFFER_SIZE - pos) ? pos * 2 : MAX_BUFFER_SIZE; if (nsz > marklimit) nsz = marklimit; byte nbuf[] = new byte[nsz]; System.arraycopy(buffer, 0, nbuf, 0, pos); if (!bufUpdater.compareAndSet(this, Buffer, nbuf)) { // of Can not IF there WAS AN buf the replace the async use Close. // Note: This Would need to BE IF changed the Fill () // IS Ever Made Accessible to Multiple Threads. // But for now , The only Way CAS CAN iS Via Fail Close. // Assert buf == null; the throw new new IOException ( "Stream Closed" ); } Buffer = nbuf were; } // set the size of POS COUNT = POS; // read length the default size of the data to the buffer, and returns the read length int n-getInIfOpen = () Read (Buffer, POS, buffer.length -. POS); IF (n-> 0 ) // to set the count to a size of length count + = n- POS; }