Channel 可以将指定的文件 或者 部分 全部映射成 Buffer
程序不能直接访问 Channel中的数据 ,读和写 都不行,Channel只能和Buffer 进行交互。
/** * 1,通道(Channel):由java.nio.channels包定义的。Channel表示 IO 元与目标打开的连接。 * Channel本身不能直接访问数据,Channel只能和Buffer配合使用 * 2,通道的实现类: * java.nio.channels.channel 接口: * --FileChannel * --SocketChannel * --ServerSocketChannel * --DatagramChannel * 3,获取通道 * 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() * * 4,通道之间的数据传输(直接缓冲区) * transferFrom(......) * 从给定的字节通道中将字节传输到该通道的文件中。 * transferTo(......) * 将通道中的字节传输到给定的可写字节的通道。 * * 5,分散(Scatter) 和聚集 (Gather) * * 分散读取(Scattering Reads) : 是指从Channel中读取的数据分散到多个Buffer中。 * 从Channel中读取的数据依次将Buffer填满。 * 聚集写入(Gathering Writes) : 是指将多个 Buffer 照片给你的数据“聚集”到Channel * 按照缓冲区的顺序,写入position 到 limit之间的数据。 */
下面看一下使用通道 完成文件的复制 :
1,利用通道完成文件的复制
//利用通道完成文件的复制(非直接缓冲区) private static void test1() { FileInputStream fis = null; FileOutputStream fos = null; FileChannel inChinnl = null; FileChannel outChinnal = null; try { fis = new FileInputStream("1.exe"); fos = new FileOutputStream("3.exe"); //获取通道 inChinnl = fis.getChannel(); outChinnal = fos.getChannel(); //分配指定大小的缓冲区 ByteBuffer buff = ByteBuffer.allocate(1024); //读取文件数据到缓冲区 while (inChinnl.read(buff) != -1) { buff.flip();//切换到读模式 //将缓冲区的数据写入到文件中 outChinnal.write(buff); buff.clear(); } } catch (Exception e) { e.printStackTrace(); try { if (inChinnl != null) inChinnl.close(); if (outChinnal != null) outChinnal.close(); if (fis != null) fis.close(); if (fos != null) fos.close(); } catch (IOException e1) { e1.printStackTrace(); } } }
2,使用 直接缓冲区完成文件的复制(内存映射文件)。
//使用直接缓冲区完成文件的复制(内存映射文件) public static void test2(){ try { //获取通道 //目标文件,也就是要放在缓冲区的文件。 StandardOpenOption.READ:代表文件可读 FileChannel inChannel = FileChannel.open(Paths.get("1.exe"), StandardOpenOption.READ); //目的文件,也就是要把缓冲区中的数据取出来,后面加的是READ/WRITE.代表文件可读可写。 //StandardOpenOption.CREATE:如果没有则创建新的。如果有直接覆盖 FileChannel outChannel = FileChannel.open(Paths.get("2.exe"),StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE); //内存映射文件(也就是创建直接缓冲区) //FileChannel.MapMode.READ_ONLY:可读 //FileChannel.MapMode.READ_WRITE:可读可写,因为这里没可写。只有可读可写。所以上面也是可读可写。 MappedByteBuffer inMap = inChannel.map(FileChannel.MapMode.READ_ONLY, 0, inChannel.size()); MappedByteBuffer outMap = outChannel.map(FileChannel.MapMode.READ_WRITE, 0, inChannel.size()); //直接对缓冲区进行数据读写 byte[] buf = new byte[inMap.limit()]; inMap.get(buf); outMap.put(buf); inChannel.close(); outChannel.close(); } catch (IOException e) { e.printStackTrace(); } }
3,使用通道进行传输(其实效果和上面的一样),也是直接缓冲区.
//通道之间的数据传输(直接缓冲区) private static void test3(){ try { FileChannel inChannel = FileChannel.open(Paths.get("1.001"),StandardOpenOption.READ); FileChannel outChannel = FileChannel.open(Paths.get("2.001"),StandardOpenOption.READ,StandardOpenOption.WRITE,StandardOpenOption.CREATE); //下面两者选其一即可. //将inChannel通道中的字节传输到给定的可写字节通道outChannel。 inChannel.transferTo(0,inChannel.size(),outChannel); //从给定的inChannel通道将字节传输到outChannel。 outChannel.transferFrom(inChannel,0,inChannel.size()); inChannel.close(); outChannel.close(); } catch (IOException e) { e.printStackTrace(); } }
4,分散读取 和 聚集写入
private static void test4(){ try { FileInputStream fis = new FileInputStream("movie.mp4"); //获取通道 FileChannel outChinnel = fis.getChannel(); //创建多个缓冲区,并放入数组 ByteBuffer byt1 = ByteBuffer.allocate(1024); ByteBuffer byt2 = ByteBuffer.allocate(1024); ByteBuffer[] byts = {byt1,byt2}; //将文件读到 多个缓冲区(byts)中 outChinnel.read(byts); fis.close(); outChinnel.close(); //将缓冲区改为可读模式 for (ByteBuffer buffer: byts) { buffer.flip(); } FileOutputStream fos = new FileOutputStream("1.mp4"); FileChannel inChannel = fos.getChannel(); //将缓冲区中的文件读出来写入到文件中. inChannel.write(byts); fos.close(); inChannel.close(); } catch (Exception e) { e.printStackTrace(); } }