Java NIO 通道(Channel) 学习笔记

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/yuzongtao/article/details/83089193

 一、通道(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();
		}
	}

 

阅读更多
换一批

没有更多推荐了,返回首页