Java NIO-之Channel与Charset

本篇文章主要介绍java8之nio相关的编码级的设置,以及通道channels的使用,如何利用通道直接复制文件等,欢迎大家交流讨论!不多说作为码农直接上代码…

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.CharBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.FileChannel.MapMode;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;
import java.nio.charset.CharsetEncoder;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import org.junit.Test;

/*
 * 一、通道(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
 * 编码:字符串 -> 字节数组
 * 解码:字节数组  -> 字符串
 * 
 */
public class Nio02 {
	//字符集如何对字符进行编码与解码
	@Test
	public void test06(){
		Charset charset=Charset.forName("GBK");
		//获取编码器 解码器
	    CharsetEncoder encoder=charset.newEncoder();
	    CharsetDecoder decoder=charset.newDecoder();
	    
	    CharBuffer ch=CharBuffer.allocate(1024);
	    ch.put("倒萨大法师帝国时代");
	    ch.flip();
	    //进行编码
	    try {
			ByteBuffer by=encoder.encode(ch);
			for(int i=0;i<18;i++){
				System.out.println(by.get());
			}
			//解码
			by.flip();
			CharBuffer charb=decoder.decode(by);
			System.out.println(charb.toString());
			
			System.out.println("-----------------------------");
			
			Charset ut=Charset.forName("UTF-8");
			by.flip();
			CharBuffer ch3=ut.decode(by);
			System.out.println(ch3.toString());
			
			
		} catch (CharacterCodingException e) {
			e.printStackTrace();
		}
	}

	//编码集 获取本地系统所支持的所有编码集 
	@Test
	public void test05(){
		Map<String, Charset> chare=Charset.availableCharsets();
		Set<Entry<String,Charset>>  set=chare.entrySet();
		for(Entry<String, Charset> enMap:set){
			System.out.println(enMap.getKey()+"--"+enMap.getValue());
		}
	}
	//分散和聚集 将通道中的数据依次按顺序写入到多个缓冲区中 (聚集则相反)
	@Test
	public void test04() throws IOException{
		try {
			@SuppressWarnings("resource")
			RandomAccessFile rAccessFile=new RandomAccessFile("1.txt", "rw");
			//获取通道
			FileChannel fChannel=rAccessFile.getChannel();
			//分配指定的缓冲区
			ByteBuffer buffer=ByteBuffer.allocate(200);
			ByteBuffer buffer1=ByteBuffer.allocate(1024);
			//分散读取
			ByteBuffer[] byteBuffer={buffer,buffer1};
			fChannel.read(byteBuffer);
				for (ByteBuffer by : byteBuffer) {
					//切换到读取模式
					by.flip();
				}
				
			System.out.println(new String(byteBuffer[0].array(), 0, byteBuffer[0].limit()));
			System.out.println("-----------------");
			System.out.println(new String(byteBuffer[1].array(), 0, byteBuffer[1].limit()));
			
			//聚集写入
			@SuppressWarnings("resource")
			RandomAccessFile wrAccessFile=new RandomAccessFile("2.txt", "rw");
			//获取通道
			FileChannel wChannel=wrAccessFile.getChannel();
			wChannel.write(byteBuffer);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
	}
	//通道之间的数据传输(直接缓冲区)
	@Test
	public void test03(){
		try {
			FileChannel iChannel=FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
			FileChannel oChannel=FileChannel.open(Paths.get("4.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE,StandardOpenOption.READ);
			//下面这两个方法是相对应的 即从哪儿来 要到哪儿去
			//iChannel.transferTo(0, iChannel.size(), oChannel);
			oChannel.transferFrom(iChannel, 0, iChannel.size());
		
		} catch (IOException e) {
			e.printStackTrace();
		}
		//内存映射文件 相当于ByteBuffer.allocateDirect(1024)
	}
	//利用直接缓冲区完成文件复制(内存映射文件)
	@Test
	public void test02(){
		try {
			//读取文件 并放入通道
			FileChannel iChannel=FileChannel.open(Paths.get("1.jpg"), StandardOpenOption.READ);
			FileChannel oChannel=FileChannel.open(Paths.get("3.jpg"), StandardOpenOption.WRITE, StandardOpenOption.CREATE,StandardOpenOption.READ);
			//内存映射文件 相当于ByteBuffer.allocateDirect(1024)
			MappedByteBuffer iBuffer=iChannel.map(MapMode.READ_ONLY, 0, iChannel.size());
			MappedByteBuffer oBuffer=oChannel.map(MapMode.READ_WRITE, 0, iChannel.size());
			//直接对缓冲区进行读写操作
			byte[] by=new byte[iBuffer.limit()];
			iBuffer.get(by);
			oBuffer.put(by);
			iChannel.close();
			oChannel.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	//利用通道完成文件复制
	@Test
	public void test01() throws IOException{
		FileInputStream inputStream=null;;
		FileOutputStream outputStream=null;
		FileChannel inChannel = null;
		FileChannel outChannel=null;
		//利用通道完成文件辅助
		try {
			 inputStream=new FileInputStream("1.jpg");
			 outputStream=new FileOutputStream("2.jpg");
			//获取通道
			 inChannel = inputStream.getChannel();
			 outChannel = outputStream.getChannel();
			//分配制定大小的缓冲区
			ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
			//将通道的数据存入缓冲区
			while (inChannel.read(byteBuffer) !=-1) {
				//切换读取数据模式
				byteBuffer.flip();
				//将缓冲区数据写入通道
				outChannel.write(byteBuffer);
				//关闭缓冲区
				byteBuffer.clear();
			}
			
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}finally{
			if(outChannel!=null){
				try {
					inChannel.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(inChannel!=null){
				try {
					outChannel.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(outputStream!=null){
				try {
					outputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
			if(inputStream!=null){
				try {
					inputStream.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
		}
		
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值