A comprehensive analysis of the working principle of Java NiO _java

Source: Internet
Author: User
Tags first row
Input/output: Conceptual description
Introduction to I/O
/ o? or input/output? Refers to the interface between a computer and the outside world or a program and the rest of the computer. It is critical for any computer system, so the body of all I/O is actually built into the operating system. Individual programs typically allow the system to do most of the work for them.
In Java programming, I/O has been completed until recently using a stream. All I/O is treated as a single byte move, moving one byte at a time through an object called a Stream. Stream I/O is used to contact the outside world. It is also used internally to convert the object to bytes and then back to the object.
NIO has the same effect and purpose as the original I/O, but does it use a different approach? Block I/O. As you will learn in this tutorial, block I/O can be much more efficient than stream I/O.
Why do you use NIO?
NIO is created to allow Java programmers to implement high speed I/O without having to write custom native code. NIO shifts the most time-consuming I/O operations (that is, the padding and extraction buffers) back to the operating system, which can greatly improve speed.
Comparison of flow and block
The most important difference between the original I/O library (in java.io.*) and NIO is the way data is packaged and transmitted. As mentioned earlier, the original I/O processes the data in a streaming manner, while NIO processes the data in a block manner.
Stream-oriented I/O systems process data One byte at a time. An input stream produces a byte of data, and an output stream consumes one byte of data. Creating filters for streaming data is easy. It is also relatively straightforward to link several filters so that each filter is responsible for only part of a single complex processing mechanism. The downside is that flow-oriented I/O is usually quite slow.
A block-oriented I/O system processes the data in block form. Each operation produces or consumes a block of data in one step. Processing data by block is much faster than processing data by (streaming) bytes. However, block-oriented I/O lacks the elegance and simplicity of some flow-oriented I/O.
Integrated I/O
The original I/O package and NIO have been well integrated in JDK 1.4. Java.io.* has been re implemented on the basis of NIO, so now it can take advantage of some of the characteristics of NIO. For example, some classes in the Java.io.* package contain methods for reading and writing data in blocks, which makes processing faster even in more flow-oriented systems.
You can also use the NIO Library to implement standard I/O functionality. For example, you can easily use block I/O to move data one byte at a time. But as you can see, NIO also offers a number of benefits that are not available in the original I/O package.
Channels and buffers
Overview
Channels and buffers are the core objects in NIO and are used in almost every I/O operation.
A channel is a simulation of a stream in the original I/O package. All data to any destination (or from any place) must pass through a Channel object. A Buffer is essentially a container object. All objects sent to a channel must first be placed in the buffer, and, similarly, any data read from the channel is read into the buffer.
In this section, you will learn how channels and buffers work in NIO.
What is a buffer?
Buffer is an object that contains some data that you want to write or just read out. Adding a Buffer object to NIO shows an important difference between the new library and the original I/O. In stream-oriented I/O, you write data directly or read data directly into a stream object.
In a NIO library, all data is processed in a buffer. When reading data, it is read directly into the buffer. When the data is written, it is written to the buffer. Any time you access data in NIO, you put it in a buffer.
The buffer is essentially an array. Typically, it is a byte array, but you can also use other kinds of arrays. But a buffer is more than just an array. Buffers provide structured access to data and can also track the read/write processes of the system.
Buffer type
The most commonly used buffer type is bytebuffer. A bytebuffer can perform get/set operations on its underlying byte array (that is, the acquisition and setting of bytes).
Bytebuffer is not the only buffer type in NIO. In fact, there is a buffer type for each of the basic Java types:
Bytebuffer
Charbuffer
Shortbuffer
Intbuffer
Longbuffer
Floatbuffer
DoubleBuffer
Each buffer class is an instance of the buffer interface. In addition to Bytebuffer, each Buffer class has exactly the same operation, except that they are dealing with different types of data. Because most standard I/O operations use Bytebuffer, it has all the shared buffer operations and some unique operations.
Now you can spend a little time running Usefloatbuffer.java, which contains an example of the type of buffer that you use.
What is a channel?
Channel is an object that can read and write data through it. Take NIO and compare it to the original I/O, the channel is like a stream.
As mentioned earlier, all data is processed by a Buffer object. You will never write bytes directly into the channel, instead, you are writing data to a buffer that contains one or more bytes. Similarly, you do not read bytes directly from the channel, but instead read the data from the channel into the buffer and get the byte from the buffer.
Channel type
The difference between a channel and a stream is that the channel is bidirectional. The stream is only moved in one Direction (a stream must be a inputstream or a outputstream subclass), and the channel can be used for reading, writing, or simultaneous reading and writing.
Because they are bidirectional, the channel can better reflect the real situation of the underlying operating system than the stream. Especially in the UNIX model, the underlying operating system channel is bidirectional.
From theory to Practice: reading and Writing in NIO
Overview
Read and write is the basic process of I/O. Reading from one channel is simple: just create a buffer and let the channel read the data into the buffer. Writing is also fairly straightforward: Create a buffer, populate it with data, and let the channel use that data to perform a write operation.
In this section, we'll learn some knowledge about reading and writing data in Java programs. We will review the main components of NIO (buffers, channels, and some related methods) to see how they interact to read and write. In the next few sections, we will analyze each of these components in more detail and their interactions.
Reading from a file
In our first exercise, we'll read some data from a file. If you use the original I/O, then we simply create a fileinputstream and read it from there. In NIO, the situation is slightly different: we first get a FileInputStream object from FileInputStream and then use this channel to read the data.
In a NIO system, any time a read operation is performed, you are read from the channel, but you are not directly reading from the channel. Because all data eventually resides in the buffer, you are read from the channel into the buffer.
So it involves three steps to read the file: (1) Get Channel from FileInputStream, (2) Create buffer, (3) Read data from Channel to buffer.
Now, let's take a look at this process.
Three easy steps
The first step is to get the channel. We get channels from FileInputStream:
Copy Code code as follows:

FileInputStream fin = new FileInputStream ("Readandshow.txt");
FileChannel FC = Fin.getchannel ();

The next step is to create a buffer:
Copy Code code as follows:

Bytebuffer buffer = bytebuffer.allocate (1024);

Finally, you need to read the data from the channel into the buffer, as follows:
Copy Code code as follows:

Fc.read (buffer);

You'll notice that we don't need to tell the channel how much data to read into the buffer. Each buffer has a complex internal statistical mechanism that tracks how much data has been read and how much space is available to hold more data.
Write to File
Writing to a file in NIO is similar to reading from a file. First get a channel from FileOutputStream:
Copy Code code as follows:

FileOutputStream fout = new FileOutputStream ("Writesomebytes.txt");
FileChannel FC = Fout.getchannel ();

The next step is to create a buffer and put some data in it--here, the data is taken out of an array named message, which contains the ASCII byte of the string "Some bytes" (explained later in this tutorial Buffer.flip () and Buffer.put () call).
Copy Code code as follows:

Bytebuffer buffer = bytebuffer.allocate (1024);
for (int i=0; i
Buffer.put (Message[i]);
}
Buffer.flip ();

The last step is in the write buffer
Copy Code code as follows:

Fc.write (buffer);

Note that there is also no need to tell the channel to write multiple data. The internal statistical mechanism of the buffer tracks how much data it contains and how much data is to be written.
Read-write combination
Next we'll look at what happens when you combine reading and writing. We use a simple program called Copyfile.java as the basis for this exercise, which copies all the contents of a file into another file. Copyfile.java performs three basic operations: first create a buffer, then read the data into the buffer from the source file, and then write the buffer to the destination file. This program repeats--reads, writes, reads, writes--until the source file is finished.
The CopyFile program lets you see how we check the status of the operation and how to use the clear () and Flip () methods to reset the buffer and prepare the buffer to write the newly read data to another channel.
Run CopyFile Example
Because the buffer tracks its own data, the internal loop of the CopyFile program (inner Loop) is very simple, as follows:
Copy Code code as follows:

Fcin.read (buffer);
Fcout.write (buffer);

The first row reads the data from the input channel fcin into the buffer, and the second line writes the data to the output channel fcout.
Check Status
The next step is to check when the copy is complete. When there is no more data, the copy is complete and can be returned in the Read () method-1 to judge this, as follows:
Copy Code code as follows:

int r = fcin.read (buffer);
if (r==-1) {
Break
}

Reset Buffer
Finally, we call the clear () method before we read the buffer from the input channel. Again, before we write the buffer to the output channel, we call the Flip () method, as shown below
Copy Code code as follows:

Buffer.clear (); int r = fcin.read (buffer);
if (r==-1) {
Break
}
Buffer.flip ();
Fcout.write (buffer);

The clear () method resets the buffer so that it can accept the read data. The flip () method allows the buffer to write newly read data to another channel.

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.