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();
				}
			}
		}
		
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章