Javaino
- That is
Java New IO
also called non-blocking IONone Blocking IO
- Is a brand new and
JDK 1.4
later providedIO API
2. Function
- Provides a
IO
differentIO
working method from the standard - Alternative to the standard
Java IO
ofIO API
3. New features
In contrast Java IO
, NIO
the new features are as follows
The main difference between Java NIO and IO
IO style | NIO style |
---|---|
Byte-oriented | Cache-oriented |
Blocking IO | Non-blocking (Non Blocking IO) |
(no) | Selectors |
4. Core components
Java NIO
The core components include:
- Channel (
Channel
) - Buffer (
Buffer
) - Selector (
Selectors
)
5. NIO_Buffer_ allocation and access
- Three important parameters in the cache
/**
* 测试缓存分配
*/
@Test
public void test1(){
// capacity 分配缓存大小
int capacity = 1024;
ByteBuffer buffer = ByteBuffer.allocate(capacity);
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println("--------------------------------------------------------");
// 向缓存中存数据 put();
buffer.put("hello world!".getBytes());
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println("--------------------------------------------------------");
//flip() 方法切换到读的状态
buffer.flip();
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println("--------------------------------------------------------");
// 从缓存中取数据 get()
//byte b = buffer.get();
byte[] dst = new byte[buffer.limit()];
buffer.get(dst);
System.out.println(new String(dst));
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println("--------------------------------------------------------");
// rewind() 重写 其起始位置从零开始
buffer.rewind();
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println("--------------------------------------------------------");
//clear() 清空缓存 限制增大 limit = capacity
buffer.clear();
System.out.println("capacity(缓存大小):" + buffer.capacity());
System.out.println("limit(限制):" + buffer.limit());
System.out.println("position(起始位置):" + buffer.position());
System.out.println((char) buffer.get());
System.out.println("--------------------------------------------------------");
}
6. Mark parameter and other methods of NIO_Buffer_ cache
/**
* 测试标记
*/
@Test
public void test2() {
// capacity 分配缓存大小
int capacity = 1024;
ByteBuffer byteBuffer = ByteBuffer.allocate(capacity);
byteBuffer.put("Hello world!".getBytes());
//flip() 方法切换到读的状态
byteBuffer.flip();
byte[] b = new byte[2];
byteBuffer.get(b);
System.out.println(new String(b));
System.out.println("--------------------------------------------------------");
System.out.println("capacity(缓存大小):" + byteBuffer.capacity());
System.out.println("limit(限制):" + byteBuffer.limit());
System.out.println("position(起始位置):" + byteBuffer.position());
// mark()做标记
byteBuffer.mark();
byteBuffer.get(b);
System.out.println(new String(b));
System.out.println("--------------------------------------------------------");
System.out.println("capacity(缓存大小):" + byteBuffer.capacity());
System.out.println("limit(限制):" + byteBuffer.limit());
System.out.println("position(起始位置):" + byteBuffer.position());
// reset()回到mark标记的位置 Invariants: mark <= position <= limit <= capacity
byteBuffer.reset();
System.out.println("--------------------------------------------------------");
System.out.println("capacity(缓存大小):" + byteBuffer.capacity());
System.out.println("limit(限制):" + byteBuffer.limit());
System.out.println("position(起始位置):" + byteBuffer.position());
}
7. NIO_Buffer_ direct cache and indirect cache
/**
* 直接缓存区
*/
@Test
public void test3(){
// 分配直接缓存区
ByteBuffer buf = ByteBuffer.allocateDirect(1024);
System.out.println("capacity(缓存大小):" + buf.capacity());
System.out.println("limit(限制):" + buf.limit());
System.out.println("position(起始位置):" + buf.position());
System.out.println("是否为直接缓存区:" + buf.isDirect());
}
8. Type and copying method of NIO_Buffer_ channel
@Test
/**
* 利用通道channel进行文件复制
*/
public void test4(){
FileInputStream fin = null;
FileOutputStream fout = null;
FileChannel finChannel = null;
FileChannel foutChannel = null;
try {
fin = new FileInputStream("3.jpg");
fout = new FileOutputStream("4.jpg");
// 获得通道
finChannel = fin.getChannel();
foutChannel = fout.getChannel();
// 获得缓存
ByteBuffer buffer = ByteBuffer.allocate(1024);//反复读3.jpg的字节到缓存 如果=1 即为读完
while(finChannel.read(buffer)!=-1){
//position定位到开头以便从缓存中获取数据
buffer.flip();
// 将缓存数据写入通道
foutChannel.write(buffer);
//清空缓存position定位到开头以便下次读通道读字节
buffer.clear();
}
} catch (Exception e) {
e.printStackTrace();
}finally {
// 关闭通道
try {
if(finChannel!=null) finChannel.close();
if(foutChannel!=null) foutChannel.close();
} catch (Exception e) {
e.printStackTrace();
}
}
}
@Test
/**
* JDK1.7之后获得的通道的方法
*/
public void test5(){
FileChannel fin = null;
FileChannel fout = null;
try {
fin = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.READ);
fout = FileChannel.open(Paths.get("5.jpg"),StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);
// 创建缓存
MappedByteBuffer finmap = fin.map(FileChannel.MapMode.READ_ONLY,0,fin.size());
MappedByteBuffer outmap = fout.map(FileChannel.MapMode.READ_WRITE,0,fin.size());
//获得3.jpg字节
byte[] dst = new byte[finmap.limit()];
finmap.get(dst);
// 把字节放入缓存
outmap.put(dst);
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(fin != null) fin.close();
if(fout != null) fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* JDK1.7之后的获取通道方法
* 通道间直接缓存交换数据
* transferFrom()
* transferTo()
*/
@Test
public void test6(){
FileChannel fin = null;
FileChannel fout = null;
try {
fin = FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.READ);
fout = FileChannel.open(Paths.get("6.jpg"),StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE_NEW);
// 创建缓存
fin.transferTo(0,fin.size(),fout);
fout.transferFrom(fin,0,fin.size());
} catch (Exception e) {
e.printStackTrace();
} finally {
try {
if(fin != null) fin.close();
if(fout != null) fin.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
9. Dispersion and aggregation of INO_Buffer
/**
* 分散和聚集
*/
@Test
public void test7() throws Exception {
// 获得通道
FileChannel channel = new RandomAccessFile("src/edu/xalead/TestBuffer.java",
"rw").getChannel();
// 创建缓存
ByteBuffer buffer1 = ByteBuffer.allocate(1024);
ByteBuffer buffer2 = ByteBuffer.allocate(1024);
ByteBuffer buffer3 = ByteBuffer.allocate(1024);
ByteBuffer buffer4 = ByteBuffer.allocate(1024);
ByteBuffer buffer5 = ByteBuffer.allocate(1024);
ByteBuffer buffer6 = ByteBuffer.allocate(1024);
ByteBuffer buffer7 = ByteBuffer.allocate(1024);
ByteBuffer buffer8 = ByteBuffer.allocate(1024);
ByteBuffer buffer9 = ByteBuffer.allocate(1024);
ByteBuffer buffer10 = ByteBuffer.allocate(1024);
// 分散读取
ByteBuffer[] buffers = {buffer1,buffer2,buffer3,buffer4, buffer5, buffer6, buffer7, buffer8,buffer9,buffer10};
channel.read(buffers);
for(ByteBuffer buffer: buffers){
System.out.println(new String(buffer.array(),0,buffer.limit()));
System.out.println("-----------------------------------------------------------");
}
//聚集写入
FileChannel channel1 = new RandomAccessFile("T.java","rw").getChannel();
// 把buffer的position恢复到起始位置
for(ByteBuffer buffer:buffers){
buffer.flip();
}
channel1.write(buffers);
channel.close();
channel1.close();
}
10 NIO summary
Buffer
Cache type (used to cache different types of data, omitting type conversion)
- ByteBuffer
- IntBuffer
- ShortBuffer
- LongBuffer
- CharBuffer
- FloatBuffer
- DoubleBuffer
Two core methods of caching and accessing data
- put () save data to cache
- get () fetch data from cache
Four parameters in the cache
- capacity
- limit
- position
- mark
Direct buffer and indirect buffer:
Non-direct buffer: allocate the buffer by the allocate () method and establish the buffer in the JVM's memory
Direct buffer: allocate the direct buffer by the allocateDirect () method and establish the buffer in the physical memory. Can improve efficiency
- The byte buffer is either direct or indirect. If it is a direct byte buffer, the Java Virtual Machine will do its best to perform native I / O operations directly on this buffer. That is to say, before each (or after) a native I / O operation of the underlying operating system is called, the virtual machine will try to avoid copying the contents of the buffer into the intermediate buffer (or copying the content from the intermediate buffer ).
- Direct byte buffers can be created by calling this class's allocateDirect () factory method. The buffers returned by this method usually cost more to allocate and deallocate than non-direct buffers. The contents of direct buffers can reside outside of the conventional garbage collection heap, so their impact on the memory requirements of the application may not be obvious. Therefore, it is recommended that direct buffers be mainly allocated to large, persistent buffers that are susceptible to the underlying system's native I / O operations. In general, it is best to allocate direct buffers only when they can provide a significant benefit in program performance.
- Direct byte buffers can also be created by directly mapping the file area into memory through the FileChannel map () method. This method returns MappedByteBuffer . The implementation of the Java platform facilitates the creation of direct byte buffers from native code through JNI. If a buffer instance in these buffers refers to an inaccessible memory area, attempting to access the area will not change the contents of the buffer, and will cause a throw during the access or at a later time Uncertain exceptions.
- Whether the byte buffer is a direct buffer or an indirect buffer can be determined by calling its isDirect () method. This method is provided to enable explicit buffer management in performance-critical code.