package com.nio.test; 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; /** * * @author fliay * * 一、通道(channel): 用于源节点与目标节点的连接。在JavaNIO中负责缓冲区中数据的传输。 * Channel本身不存在存数据,因此需要配合缓冲区进行传输。 * * 二、通道的主要实体类 * |--FileChannel * |--SocketChannel * |--ServerSocketChannel * |--DatagramChannel * * 三、获取通道 1.Java针对支持通道的类提供了getChannel()方法 本地IO: * FileInputStream/FileOutputStream RandomAccessFile * * 网络IO * |--Socket * |--ServerSocket * |--DatagramSocket * * 2.在JDK1.7中的NIO.2针对各个通道提供了静态方法open() * 3.在JDK1.7中的NIO.2的file工具类的newByteChannel() * * 四、通道之间的数据传输 * transferFrom() * transferTo() * * 五、分散(Scatter)与聚集() * */ public class TestChannel { // 利用通道完成文件的复制 @Test public void test1() { long start = System.currentTimeMillis(); FileInputStream fis = null; FileOutputStream fos = null; FileChannel inChannel = null; FileChannel outChannel = null; try { // cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408 大小为3.42G fis = new FileInputStream("/虚拟机/cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso"); fos = new FileOutputStream("/开发/cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso"); // 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 (FileNotFoundException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } finally { try { outChannel.close(); inChannel.close(); fos.close(); fis.close(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } } long end = System.currentTimeMillis(); System.out.println("消耗时间为:" + (end - start)); } // 消耗时间为:12651 // 使用直接缓冲区完成文件的复制(内存映射文件) @Test public void Test2() throws IOException { long start = System.currentTimeMillis(); FileChannel inChannel = FileChannel.open(Paths.get("/虚拟机/cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso"), StandardOpenOption.READ); FileChannel outChannel = FileChannel.open(Paths.get("/开发/cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE); // long[] sizes = new long[3]; // 如果文件过长的话会报错 Size exceeds Integer.MAX_VALUE 可以通过对文件进行分批存 // sizes[0]=0; // sizes[1]=inChannel.size()/2; // sizes[2]=inChannel.size()-inChannel.size()/2; // for(int i=0;i<sizes.length-1;i++){ // //内存映射文件 // MappedByteBuffer inMappedBuf = inChannel.map(MapMode.READ_ONLY, // sizes[i],sizes[i+1]); // MappedByteBuffer outMappedBuf = outChannel.map(MapMode.READ_WRITE, // sizes[i],sizes[i+1]); // //直接对缓冲区进行数据的读写操作 // byte[] dst = new byte[inMappedBuf.limit()]; // inMappedBuf.get(dst); // outMappedBuf.put(dst); // } // 内存映射文件 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); inChannel.close(); outChannel.close(); long end = System.currentTimeMillis(); System.out.println("消耗时间为:" + (end - start)); }// 执行时间6161 // 通道之间的数据传输 @Test public void Test3() throws IOException { long start = System.currentTimeMillis(); FileChannel inChannel = FileChannel.open(Paths.get("/虚拟机/cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso"), StandardOpenOption.READ); FileChannel outChannel = FileChannel.open(Paths.get("/开发/cn_windows_7_ultimate_with_sp1_x64_dvd_u_677408.iso"), StandardOpenOption.WRITE, StandardOpenOption.READ, StandardOpenOption.CREATE); // inChannel.transferTo(0, inChannel.size(), outChannel);//执行时间为3957 // 但是文件为拷贝完,只拷贝了2/3 outChannel.transferFrom(inChannel, 0, inChannel.size());// 执行时间8313 成功拷贝 inChannel.close(); outChannel.close(); long end = System.currentTimeMillis(); System.out.println("消耗时间为:" + (end - start)); } //分散和聚集 @Test public void Test4() throws IOException{ RandomAccessFile ref1 = new RandomAccessFile("/Study/JavaSite/JaveNIO/src/main/java/com/nio/test/TestChannel.java","rw"); //1.获取通道 FileChannel channel1 = ref1.getChannel(); //2.分配指定大小的缓冲区 ByteBuffer buf1 = ByteBuffer.allocate(100); ByteBuffer buf2 = ByteBuffer.allocate(1024); //3.分散读取 ByteBuffer[] bufs ={buf1,buf2}; channel1.read(bufs); for(ByteBuffer byteBuffer:bufs){ byteBuffer.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 ref2 = new RandomAccessFile("/Study/JavaSite/JaveNIO/src/main/java/com/nio/test/TestChannel2.java","rw"); FileChannel channel2 = ref2.getChannel(); channel2.write(bufs); } }