Reference document: Getting started with new I/O (NIO)

Preface:

NIO was introduced with JDK1.4 for high speed, block oriented I/O in standard Java code. By defining classes to hold data, and by processing that data in blocks, NIO takes advantage of low-level optimizaitons compared to I/O package could not, without using native libraries.

We will cover most aspect of the NIO library, from high level conceptual stuff to under-the-hood programming detail. To learning about crucial I/O elements like buffers and channels, we will also see how standard I/O elements works in the updated library. You'll also learn about things you can only do with NIO, such as asynchronous I/O and direct buffers.

Input/output: A conceptual overview

I/O in Java programming, I/O has until recently been carried out using a stream metaphor. All I/O is viewed as the movement of single bytes, one at a time, through an object called a stream. Stream I/O is used for contacting the outside world, and it can also used internally for turning objects into bytes and then back into objects.

NIO plays the same role as original I/O, but it uses a different metaphor -- block I/O. As you can see the Java NIO Buffers, the block I/O is more efficient than stream I/O.

Why NIO?

NIO was created allow Java program to implement high-speed I/O without having to write custom native code. NIO moves the most time-consuming I/O activities(namely, filling and draining buffers) back into the OS, thus allowing great increase in speed.

Streams vs blocks

The most important distinction between the original I/O library and NIO has to do with how data is packaged and transmitted. The original I/O deals with data in streams, whereas NIO do with data in blocks.

A stream-oriented I/O system deals with data one byte at a time. An input stream produces one byte of data, and an output stream consumes one byte of data. It's very easy to create filters for stream data , also relatively simply to chain several filters together so that each one does its part in what amounts to single sophisticated processing mechanism. On the flip side, stream-oriented I/O is often rather slow.

Integrated I/O

The original I/O package and NIO have been well integrated in JDK 1.4 java.io.* has been reimplemented using NIO as its base , so it can now take advantage of some features of NIO. For example some java some of classes in the java.io.* package contain methods to read and write data in blocks, which leads to faster processing.

Channel and buffers

Channels and buffers are the central
objects in NIO, and are used for just about every I/O operation.
Channels are analogous to stream in the original IO package. All data
that goes anywhere must pass through a Channel object. A buffer is
essentially a container object. All data that is sent to a channel
must first be placed in a buffer. So any data that is read from a
channel is read into buffer.

What
is a buffer?

A buffer is an object, which is essentially an array. It's an
array of bytes, but other kinds of arrays can be used. But a buffer
is more than just an array. A buffer provides structured access to
data and also keeps track of the system's read/write processes.

In the NIO library, all data is handled with buffers. When data is
read, it's read directly into a buffer, when data is written, it's
written into a buffer. Anytime you access data in NIO, you are
pulling it out of the buffer. A buffer is essentially an array.

What 's a channel ?
A channel is an object from which you can
read data and to which you can write data.Comparing NIO with original
I/O, a channel is like a stream.

Kinds of Channel

Channels differ from stream in that they are bi-directional.
Whereas streams only go in one direction (a stream must be a subclass
of either InputStream or OutputStream), a channel can be opened for
reading, for writing, or for both.

Because they are bi-directional, channels better reflect the
reality of the underlying OS than streams do. In the UNIX model in
particular, the underlying OS channels are bi-directional.

Practice: Reading and
writing in NIO

Reading from a channel is simple: we create a buffer and then ask
a channel to read data into it. Writing data we just create a buffer,
fill it will data, and then ask a channel to write from it.

Reading from a file

For our first exercise, we'll read some data from a file. If we
are using original IO, we will simply create a FileInputStream and
read from that.

In NIO, however, things work a little differently; we first get Channel object from the FileInputStream, and then use that channel to read the data.

Any time you perform a read operation in an NIO system.you are reading from a channel, but you don’t read directly from  a channel. Since the data ultimate resides in the buffer, you read from a channel to a buffer.

So reading from a file involves three steps:

  1. getting the Channel from FileInputStream;
  2. creating the Buffer
  3. reading from the Channel into the buffer

Three easy steps:
Our first step is to get a channel. We get the channel from the FileInputStream.

FileInputStream fin = new FileInputStream("DirectMem.java");
FileChannel fc = fin.getChannel();

The next step is to create a buffer and read from the channel into the buffer, as shown here:

ByteBuffer buffer = ByteBuffer.allocate(1024);
fc.read(buffer);

We don't need to tell the channel how much to read into buffer. Each buffer has ssophisticated internal accounting system that keeps track of how much data has been read and how much room there is for more data. We will discuss the Buffer internals overview then.

Writing to a file

Writing is similiar to reading from a file. Here is the sample code:

    private static void readingWritingFromFile() throws IOException{
String fileName = "DirectMem.java";
FileInputStream fin = new FileInputStream(fileName);
FileChannel fc = fin.getChannel(); int bufLen = 2<<10;
ByteBuffer buffer = ByteBuffer.allocate(bufLen);
fc.read(buffer); String newFileName = "newDirectMem.txt";
FileOutputStream fout = new FileOutputStream(newFileName);
FileChannel writeFc = fout.getChannel(); ByteBuffer newBuf = ByteBuffer.allocate(bufLen);
String message = "test writing to channel from buffer";
byte[] mesArray = message.getBytes();
for (int i = 0; i < mesArray.length; i++) {
newBuf.put(mesArray[i]);
}
newBuf.flip();
writeFc.write(newBuf); }

Other reading and writing operation please see Reading and Writing with Java NIO

There some examples we combine reads data into the buffer from the input channel, fcin, and the second line writes the data to the output channel, fcout. Notice that before reading into a buffer from the input channel we call the method clear(), and before write newly read data into another channel we call the flip() method prepare the buffer.

Buffer internals

In this section, we will see 2 components of buffers in NIO: state variables and accessor methods.

State variables are key to the "internal accouting system" mentioned in the previous section. With each read/write operation, the internal states changes. By recording and tracking those changes, a buffer is can manage it's own resources.

A buffer has many states, in some cases write data directly into another channel, but often you'll want to look at the data itself. This is acopmlished using the accessor method get(), while if if you want to put raw data in a buffer, you use the accessor method put().

State variables

3 values can be used to specify the state of a buffer:

  • position
  • limit
  • capacity

these variables track the state of the buffer and the data is contains. We'll examine each one in detail, and also see how to fit read/write process. For the sake of the example, we'll assume that we are copying data from an input channel to an output channel.

Position

You will recall that a buffer is really just a glorified array when you read from a channel, position records how much data you have written. It specifies into where is array element the next byte. If you write to a channel, postion will record how much data read from the buffer. It refers to the next eelement you want to read.

Limit

The limit variable specifies how much data there is left to get, or how much room left to put data into.

Capacity

The capacity of a buffer sepcifies the maximum amount of data that can be stored therein. It specifies the size of underlyging array.

The limit is smaller than capacity.

We create buffer as example, let's assume that our buffer capacity is 8 bytes, and the buffer states is shown:

React operations

The limit can not be larger than the ccapacity, and in this case both values are set to 8. We show this by pointing them off the end of the array. The position is set to 0, when read data into the buffer, then the next byte read will be put into slot0; If we write from the buffer, the next byte taken from the buffer will be taken from slot 0.

React operations

When we read data into the buffer, increase the position. In this example we read 5 bytes so add 5 to pposition.

After read byte into buffer from channel, we want write bytes from buffer to channel. But before change ooperation to buffer, we should first call the flip() function. It resets position to 0, and set limit to the position old value.

React operations

You can see the posiiton set to 0 and limit set to 5(Meaning all data we read from buffer just now), Then we begin write bytes from the buffer to channel. And we read 5 bytes from the buffer, add 5 to position and now you can see position is equal to limit.

When all read and write operations finished, we call clear() method to clear all variables:

1. reset positon to 0.

2. limit set to capacity

Conclusion

If you want manipulate data in disk you should firstly read it into buffer from the channel, or if you want to store data back to disk you should write channel from the buffer.

For more detail about manipulation about buffer, please see Java NIO read/write file through FileChannel

brief introduction JAVA new I/O (NIO)的更多相关文章

  1. Java I/O and NIO [reproduced]

    Java I/O and NIO.2---Five ways to maximize Java NIO and NIO.2---Build more responsive Java applicati ...

  2. Java网络编程和NIO详解开篇:Java网络编程基础

    Java网络编程和NIO详解开篇:Java网络编程基础 计算机网络编程基础 转自:https://mp.weixin.qq.com/s/XXMz5uAFSsPdg38bth2jAA 我们是幸运的,因为 ...

  3. Java网络编程和NIO详解8:浅析mmap和Direct Buffer

    Java网络编程与NIO详解8:浅析mmap和Direct Buffer 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NI ...

  4. Java网络编程和NIO详解9:基于NIO的网络编程框架Netty

    Java网络编程和NIO详解9:基于NIO的网络编程框架Netty 转自https://sylvanassun.github.io/2017/11/30/2017-11-30-netty_introd ...

  5. Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理

    Java网络编程和NIO详解7:浅谈 Linux 中NIO Selector 的实现原理 转自:https://www.jianshu.com/p/2b71ea919d49 本系列文章首发于我的个人博 ...

  6. Java网络编程和NIO详解6:Linux epoll实现原理详解

    Java网络编程和NIO详解6:Linux epoll实现原理详解 本系列文章首发于我的个人博客:https://h2pl.github.io/ 欢迎阅览我的CSDN专栏:Java网络编程和NIO h ...

  7. Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO

    Java网络编程和NIO详解5:Java 非阻塞 IO 和异步 IO Java 非阻塞 IO 和异步 IO 转自https://www.javadoop.com/post/nio-and-aio 本系 ...

  8. Java网络编程和NIO详解4:浅析NIO包中的Buffer、Channel 和 Selector

    Java网络编程与NIO详解4:浅析NIO包中的Buffer.Channel 和 Selector 转自https://www.javadoop.com/post/nio-and-aio 本系列文章首 ...

  9. Java网络编程和NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型

    Java网络编程与NIO详解2:JAVA NIO一步步构建IO多路复用的请求模型 知识点 nio 下 I/O 阻塞与非阻塞实现 SocketChannel 介绍 I/O 多路复用的原理 事件选择器与 ...

随机推荐

  1. CRM Entity 之Money转string int类型等

    Money转string 左右都是string //服务站地址 vehicleDetail["yt_servicestation_address"]=serviceStationC ...

  2. iOS百度推送的基本使用

    一.iOS证书指导 在 iOS App 中加入消息推送功能时,必须要在 Apple 的开发者中心网站上申请推送证书,每一个 App 需要申请两个证书,一个在开发测试环境下使用,另一个用于上线到 App ...

  3. css学习知识点

    各个前缀所代表的浏览器: Webkit: chrome, safari[也有可能是opera] Moz: 火狐 Ms: 主要是IE O: opera border-radius:  IE9  -web ...

  4. CCF计算机认证注意事项

    1,同一变量只使用一次,你是使用同名的局部变量. 2,if()条件语句里面再不要使用单一的if()条件语句. 这应该都是他们系统的bug

  5. [一个经典的多线程同步问题]解决方案三:互斥量Mutex

    本篇通过互斥量来解决线程的同步,学习其中的一些知识. 互斥量也是一个内核对象,它用来确保一个线程独占一个资源的访问.互斥量与关键段的行为非常相似,并且互斥量可以用于不同进程中的线程互斥访问资源.使用互 ...

  6. AutoCompleteTextview、MultiAutoCompleteTextView

    AutoCompleteTextview     动态匹配输入内容文本框      属性:           android:completionThreshold="2";   ...

  7. getElementByID、getElementsByName、getElementsByTagName实例详解

    getElementByID.getElementsByName.getElementsByTagName实例详解 本文通过实例,详细介绍了getElementByID.getElementsByNa ...

  8. MYSQL中的普通索引,主健,唯一,全文索引区别

    MYSQL索引用来快速地寻找那些具有特定值的记录,所有MySQL索引都以B-树的形式保存.如果没有索引,执行查询时MySQL必须从第一个记录开始扫描整个表的所有记录,直至找到符合要求的记录.表里面的记 ...

  9. ParseChat应用源码ios版

    ParseChat是一个完全原生的iPhone应用程序,用于创建实时的.基于文本的Parse聊天室.功能:支持多台设备之间的实时聊天,可动态添加新的聊天室,支持基本配置,可发送和接收音效以及任意大小的 ...

  10. ubuntu远程windows服务器

    ubuntu端: sudo apt-get install rdesktop windows端: 需要允许此windows远程访问.我的windows是windows server2012,基本操作: ...