java基礎:NIO之非同步FileChannel和Charset(5)
AsynchronousFileChannel
在 Java 7 中,Java NIO 中添加了 AsynchronousFileChannel,也就是是非同步地將數 據寫入檔案。
建立 AsynchronousFileChannel
通過靜態方法 open()建立
Path path = Paths.get("d:\\1.txt");
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);
open()方法的第一個引數指向與 AsynchronousFileChannel
第二個引數是一個或多個開啟選項,它告訴 AsynchronousFileChannel
在檔案上執行什麼操作。在本例中,我們使用了 StandardOpenOption.READ
選項,表示該檔案將被開啟閱讀。
通過 Future 讀取資料
可以通過兩種方式從 AsynchronousFileChannel
讀取資料。第一種方式是呼叫返回 Future
的 read()方法
Path path = Paths.get("d:\\1.txt"); AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ); ByteBuffer buffer = ByteBuffer.allocate(1024); long position = 0; Future<Integer> operation = fileChannel.read(buffer, position); while(!operation.isDone()); //返回讀取到的位元組數目 System.out.println(operation.get()); buffer.flip(); byte[] data = new byte[buffer.limit()]; buffer.get(data); System.out.println(new String(data)); buffer.clear();
上述程式碼:
(1)建立了一個 AsynchronousFileChannel
(2)建立一個 ByteBuffer,它被傳遞給 read()方法作為引數,以及一個 0 的位置。
(3)在呼叫 read()之後,迴圈,直到返回的 isDone()方法返回 true。
(4)讀取操作完成後,資料讀取到 ByteBuffer 中,然後列印到 System.out 中。
通過 CompletionHandler 讀取資料
第二種方法是呼叫 read()方法,該方法將一個 CompletionHandler
作為引數
示例:
Path path = Paths.get("d:\\1.txt"); AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.READ);; ByteBuffer buffer = ByteBuffer.allocate(1024); long position = 0; fileChannel.read(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() { //result 讀取到的位元組數目 @Override public void completed(Integer result, ByteBuffer attachment) { System.out.println("result = " + result); attachment.flip(); byte[] data = new byte[attachment.limit()]; attachment.get(data); System.out.println(new String(data)); attachment.clear(); } @Override public void failed(Throwable exc, ByteBuffer attachment) { } });
(1)讀取操作完成,將呼叫 CompletionHandler
的 completed()
方法。
(2)對於completed()方法的引數傳遞一個整數,它告訴我們讀取了多少位元組,以及傳遞給 read()方法的“附件”。“附件”是 read()方法的第三個引數。在本程式碼中,它是 ByteBuffer,資料也被讀取。
(3)如果讀取操作失敗,則將呼叫 CompletionHandler
的 failed()
方法。
通過 Future和CompletionHandler 寫入資料
大部分程式碼與上面程式碼類似,這裡不過多介紹。
Future
寫入資料:open時指定StandardOpenOption.WRITE
寫操作
AsynchronousFileChannel fileChannel = AsynchronousFileChannel.open(path, StandardOpenOption.WRITE);
Future<Integer> operation = fileChannel.write(buffer, position);
buffer.clear();
while(!operation.isDone());
System.out.println("Write over");
CompletionHandler
方式寫入資料:
fileChannel.write(buffer, position, buffer, new CompletionHandler<Integer, ByteBuffer>() {
@Override
public void completed(Integer result, ByteBuffer attachment) {
System.out.println("bytes written: " + result);
}
@Override
public void failed(Throwable exc, ByteBuffer attachment) {
System.out.println("Write failed");
exc.printStackTrace();
}
});
當寫操作完成時,將會呼叫 CompletionHandler
的 completed()
方法。如果寫失 敗,則會呼叫 failed()
方法。
字符集(Charset)
java 中使用 Charset 來表示字符集編碼物件
Charset 常用靜態方法
public static Charset forName(String charsetName)//通過編碼型別獲得 Charset 物件
public static SortedMap<String,Charset> availableCharsets()//獲得系統支援的所有編碼方式
public static Charset defaultCharset()//獲得虛擬機器預設的編碼方式
public static boolean isSupported(String charsetName)//判斷是否支援該編碼型別
Charset 常用普通方法
public final String name()//獲得 Charset 物件的編碼型別(String)
public abstract CharsetEncoder newEncoder()//獲得編碼器物件
public abstract CharsetDecoder newDecoder()//獲得解碼器物件
示例:
Charset charset = Charset.forName("UTF-8");
//1.獲取編碼器
CharsetEncoder charsetEncoder = charset.newEncoder();
//2.獲取解碼器
CharsetDecoder charsetDecoder = charset.newDecoder();
//3.獲取需要解碼編碼的資料
CharBuffer charBuffer = CharBuffer.allocate(1024);
charBuffer.put("字符集編碼解碼");
charBuffer.flip();
//4.編碼
ByteBuffer byteBuffer = charsetEncoder.encode(charBuffer);
System.out.println("編碼後:");
for (int i=0; i<byteBuffer.limit(); i++) {
System.out.println(byteBuffer.get());
}
//5.解碼
byteBuffer.flip();
CharBuffer charBuffer1 = charsetDecoder.decode(byteBuffer);
System.out.println("解碼後:");
System.out.println(charBuffer1.toString());
System.out.println("指定其他格式解碼:");
Charset charset1 = Charset.forName("GBK");
byteBuffer.flip();
CharBuffer charBuffer2 = charset1.decode(byteBuffer);
System.out.println(charBuffer2.toString());
//6.獲取 Charset 所支援的字元編碼
Map<String ,Charset> map = Charset.availableCharsets();
Set<Map.Entry<String,Charset>> set = map.entrySet();
for (Map.Entry<String,Charset> entry: set) {
System.out.println(entry.getKey() + "=" + entry.getValue().toString());
}
執行結果: