1. 程式人生 > 其它 >java基礎:NIO之非同步FileChannel和Charset(5)

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

相關聯檔案的 Path 例項。

第二個引數是一個或多個開啟選項,它告訴 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)讀取操作完成,將呼叫 CompletionHandlercompleted()方法。

(2)對於completed()方法的引數傳遞一個整數,它告訴我們讀取了多少位元組,以及傳遞給 read()方法的“附件”。“附件”是 read()方法的第三個引數。在本程式碼中,它是 ByteBuffer,資料也被讀取。

(3)如果讀取操作失敗,則將呼叫 CompletionHandlerfailed()方法。

通過 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();
     }
});

當寫操作完成時,將會呼叫 CompletionHandlercompleted()方法。如果寫失 敗,則會呼叫 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());
        }

執行結果: