Java NIO 通道(Channel) 學習筆記
阿新 • • 發佈:2018-11-20
一、通道(Channel):用於源節點與目標節點的連線。在 Java NIO 中負責緩衝區中資料的傳輸。Channel 本身不儲存資料,因此需要配合緩衝區進行傳輸。
二、通道的主要實現類
java.nio.channels.Channel 介面:
|--FileChannel
|--SocketChannel
|--ServerSocketChannel
|--DatagramChannel
三、獲取通道
1. Java 針對支援通道的類提供了 getChannel() 方法
本地 IO:
FileInputStream/FileOutputStream
RandomAccessFile
網路IO:
Socket
ServerSocket
DatagramSocket
2. 在 JDK 1.7 中的 NIO.2 針對各個通道提供了靜態方法 open()
3. 在 JDK 1.7 中的 NIO.2 的 Files 工具類的 newByteChannel()
四、通道之間的資料傳輸
transferFrom()
transferTo()
五、分散(Scatter)與聚集(Gather)
分散讀取(Scattering Reads):
聚集寫入(Gathering Writes):將多個緩衝區中的資料聚集到通道中
六、字符集:Charset
編碼:字串 -> 位元組陣列
解碼:位元組陣列 -> 字串
Channel程式碼例項:利用通道完成檔案的複製
1.非直接緩衝區
//利用通道完成檔案的複製(非直接緩衝區) @Test public void testChannel(){ long start = System.currentTimeMillis(); FileInputStream fis = null; FileOutputStream fos = null; //1. 獲取通道 FileChannel inChannel = null; FileChannel outChannel = null; try{ fis = new FileInputStream("G:/MP4/00.mp4"); fos = new FileOutputStream("G:/MP4/01.mp4"); inChannel = fis.getChannel(); outChannel = fos.getChannel(); //2. 分配指定大小的非直接緩衝區 ByteBuffer buff = ByteBuffer.allocate(1024); //3. 將通道中的資料存入緩衝區中 while(inChannel.read(buff) != -1){ buff.flip(); //切換讀取資料的模式 //4.將緩衝區中的資料寫入通道中 outChannel.write(buff); buff.clear(); //清空緩衝區 } }catch(IOException e){ e.printStackTrace(); }finally{ if(fis != null){ try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } if(fos != null){ try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if(inChannel != null){ try { inChannel.close(); } catch (IOException e) { e.printStackTrace(); } } if(outChannel != null){ try { outChannel.close(); } catch (IOException e) { e.printStackTrace(); } } } long end = System.currentTimeMillis(); System.out.println("耗費時間為:" + (end - start)); }
2.直接緩衝區
@Test
public void testFileChannel(){
long start = System.currentTimeMillis();
try {
FileChannel inChannel = FileChannel.open(Paths.get("G:/MP4/00.mp4"), StandardOpenOption.READ);
FileChannel outChannel = FileChannel.open(Paths.get("G:/MP4/04.mp4"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE);
// start 1.第一種實現方式:使用直接緩衝區完成檔案的複製(記憶體對映檔案)
MappedByteBuffer inMappedBuf = inChannel.map(MapMode.READ_ONLY, 0, inChannel.size());
MappedByteBuffer outMappedBuf = outChannel.map(MapMode.READ_WRITE, 0, inChannel.size());
//直接對緩衝區進行資料的讀寫操作
byte[] dst = new byte[inMappedBuf.limit()];
inMappedBuf.get(dst);
outMappedBuf.put(dst);
// end 1.第一種實現方式:使用直接緩衝區完成檔案的複製(記憶體對映檔案)
// start 2.第二種實現方式:通道之間的資料傳輸(直接緩衝區) transferTo || transferFrom
inChannel.transferTo(0, inChannel.size(), outChannel);
// outChannel.transferFrom(inChannel, 0, inChannel.size());
// end 2.第二種實現方式:通道之間的資料傳輸(直接緩衝區) transferTo || transferFrom
inChannel.close();
outChannel.close();
long end = System.currentTimeMillis();
System.out.println("耗費時間為:" + (end - start));
} catch (IOException e) {
e.printStackTrace();
}
}