通道(Channel):由 java.nio.channels 包定義 的。Channel 表示 IO 源與目標打開的連接。
Channel 類似於傳統的“流”。只不過 Channel 本身不能直接訪問數據,Channel 只能與 Buffer 進行交互
TestChannel
package com.aff.nio; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.FileOutputStream; import java.io.IOException; import java.io.RandomAccessFile; import java.nio.ByteBuffer; import java.nio.MappedByteBuffer; import java.nio.channels.FileChannel; import java.nio.channels.FileChannel.MapMode; import java.nio.file.Paths; import java.nio.file.StandardOpenOption; import org.junit.Test; /* * 1.通道(channel):用於源節點於目標節點的連接,在Java NIO中負責緩沖區數據的傳輸。 * channel本身不存儲數據的,因此需要配合緩沖區傳輸‘ * 2.通道的主要實現類 * java.nio.channels.Channel接口 * |FileChannel 本地的文件通道 * |SocketChannel 網絡 TCP * |ServerSocketChannel 網絡TCP * |DatagramChannel 網絡 UDP * * 3.獲取通道 * ①.java針對支持通道的類提供了getChannel()方法 * * 本地: * FileInputStream/FileOutputStream * RandomAccessFile//隨機存儲文件流 * * 網絡IO: * Socket * ServerSocket * DatagremSocket * * ②.jdk1.7NIO.2針對各個通道提供靜態方法open() * ③.jdk1.7中的NIO.2的Files工具類的newByteChannel() * 4.通道之間的數據傳輸 * transferFrom() * transferTo() * * 5. * 分散(Scatter)與聚集(Gather) * 分散讀取(Scattering Reads):將通道中的數據分散到多個緩沖區中 * 聚集寫入(Gathering Writes):將多個緩沖區中的數據聚集到通道中 * * 6.字符集:Charset * 編碼:字符串->字節數組 * 解碼:字節數組->字符串 */ public class TestChannel { // 分散和聚集 @Test public void test4() throws IOException { RandomAccessFile raf = new RandomAccessFile("11.txt", "rw"); // 分散讀取,通道中數據分散到多個緩沖區中 // 1.獲取通道 FileChannel channel = raf.getChannel(); // 2.分配通道大小 ByteBuffer buf1 = ByteBuffer.allocate(100); ByteBuffer buf2 = ByteBuffer.allocate(500); // 3.分散讀取 ByteBuffer[] bufs = { buf1, buf2 }; channel.read(bufs); for (ByteBuffer by : bufs) { by.flip(); } System.out.println(new String(bufs[0].array(), 0, bufs[0].limit())); System.out.println("================="); System.out.println(new String(bufs[1].array(), 0, bufs[1].limit())); // 4.聚集寫入 RandomAccessFile raf2 = new RandomAccessFile("16.txt", "rw"); FileChannel channel2 = raf2.getChannel(); channel2.write(bufs); } // 通道之間的數據傳輸(直接緩沖區) @Test public void test3() throws IOException { FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"),
StandardOpenOption.READ); FileChannel outChannel = FileChannel.open(Paths.get("4.jpg"),
StandardOpenOption.WRITE,
StandardOpenOption.READ,StandardOpenOption.CREATE);
inChannel.transferTo(0, inChannel.size(), outChannel);
// 從inchannel來到outchannel中去 // inChannel.transferTo(position, count, target) // outChannel.transferFrom(inChannel, 0, inChannel.size()); // outChannel.transferFrom(src, position, count) } // 使用直接緩沖區完成文件的復制(內存映射文件的方) @Test public void test2() throws Exception { long start = System.currentTimeMillis(); FileChannel inChannel = FileChannel.open(Paths.get("1.jpg"),
StandardOpenOption.READ); FileChannel outChannel = FileChannel.open(Paths.get("3.jpg"),
StandardOpenOption.WRITE,StandardOpenOption.READ,
StandardOpenOption.CREATE); // 內存映射文件 MappedByteBuffer inMappedByteBuffer = inChannel.map(MapMode.READ_ONLY, 0,
inChannel.size()); MappedByteBuffer outMappedByteBuffer = outChannel.map(MapMode.READ_WRITE, 0,
inChannel.size()); // 直接對緩沖區進行數據的讀寫操作 byte[] dst = new byte[inMappedByteBuffer.limit()]; inMappedByteBuffer.get(dst); outMappedByteBuffer.put(dst); inChannel.close(); outChannel.close(); long end = System.currentTimeMillis(); System.out.println("時間為:" + (end - start));// 7 } // 使用通道完成文件的復制(非直接緩沖區) @Test public void test1() throws FileNotFoundException { long start = System.currentTimeMillis(); FileInputStream fis = null; FileOutputStream fos = null; FileChannel inchannel = null; FileChannel outchannel = null; try { fis = new FileInputStream("1.jpg"); fos = new FileOutputStream("2.jpg"); // 1.獲取通道 inchannel = fis.getChannel(); outchannel = fos.getChannel(); // 2.分配指定大小的緩沖區 ByteBuffer buf = ByteBuffer.allocate(1024); // 3.將通道中的數據存入緩沖區中 while ((inchannel.read(buf)) != -1) { buf.flip(); // 然后切換成讀取模式,再輸出 // 4.將緩沖區的數據寫入通道中 outchannel.write(buf); buf.clear();// 清空緩沖區 } } catch (IOException e) { e.printStackTrace(); } finally { if (outchannel != null) { try { outchannel.close(); } catch (IOException e) { e.printStackTrace(); } } if (inchannel != null) { try { inchannel.close(); } catch (IOException e) { e.printStackTrace(); } } if (fos != null) { try { fos.close(); } catch (IOException e) { e.printStackTrace(); } } if (fis != null) { try { fis.close(); } catch (IOException e) { e.printStackTrace(); } } } long end = System.currentTimeMillis(); System.out.println("時間為:" + (end - start));// 146 } }