ThinkJava-新IO

來源:互聯網
上載者:User

標籤:目標   編碼   image   mac   關閉   表示   length   速度   class   

package com.java.io;import java.io.FileInputStream;import java.io.FileOutputStream;import java.io.RandomAccessFile;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;public class GetChannel {      private static final int BSIZE = 1024;            @SuppressWarnings("resource")      public static void main(String[] args) throws Exception {              // 擷取通道,該通道允許寫操作            FileChannel fc = new FileOutputStream("data.txt").getChannel();            // 將位元組數組封裝到緩衝區中            fc.write(ByteBuffer.wrap("Some text ".getBytes()));            // 關閉通道            fc.close();                        // 隨機讀寫檔案流建立的管道            fc = new RandomAccessFile("data.txt", "rw").getChannel();            // fc.position()計算從檔案的開始到當前位置之間的位元組數            // 設定此通道的檔案位置,fc.size()此通道的檔案的當前大小,該條語句執行後,通道位置處於檔案的末尾            fc.position(fc.size()); // Move to the end            fc.write(ByteBuffer.wrap("Some more".getBytes()));            fc.close();                        // Read the file:            fc = new FileInputStream("data.txt").getChannel();            ByteBuffer buff = ByteBuffer.allocate(BSIZE);            // 將檔案內容讀到指定的緩衝區中            fc.read(buff);            //buffer.flip();一定得有,如果沒有,就是從檔案最後開始讀取的,當然讀出來的都是byte=0時候的字元。            //通過buffer.flip();這個語句,就能把buffer的當前位置更改為buffer緩衝區的第一個位置。            buff.flip();            while(buff.hasRemaining()){                System.out.print((char)buff.get());            }      }}
View Code對於唯讀訪問,我們必須顯式地使用靜態allocate()方法來分配ByteBuffer。 nio的目標就是快速移動大量資料,因此ByteBuffer的大小就顯得尤為重要一一實際上,這裡使用的lK可能比我們通常要使用的小一點(必須通過實際運行應用程式來找到最佳尺寸). 一旦調用read()來告知FileChannel向ByteBuffer儲存位元組,就必須調用緩衝器上的flip(). 讓它做好讓別人讀取位元組的準備(是的,這似乎有一點拙劣,但是請記住,它是很拙劣的,但卻適用於在取最大速度) 如果我們打算使用緩衝器執行進一步的read()操作,我們也必須得調用clear()來為每個read()做好準備.這在下面這個簡單檔案複製程式中可以看到: 
package com.java.io;import java.io.FileInputStream;import java.io.FileOutputStream;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;public class ChannelCopy {      private static final int BSIZE = 1024;      public static void main(String[] args) throws Exception {            if(args.length != 2) {              System.out.println("arguments: sourcefile destfile");              System.exit(1);            }            FileChannel in = new FileInputStream(args[0]).getChannel(),                        out = new FileOutputStream(args[1]).getChannel();            ByteBuffer buffer = ByteBuffer.allocate(BSIZE);            while(in.read(buffer) != -1) {              buffer.flip();     // Prepare for writing              out.write(buffer);              buffer.clear();    // Prepare for reading            }       }}
View Code可以看到,開啟~個FileChannel以用於讀,而開啟另一個以用於寫。ByteBuffer被分配了空間,當FileChannel.read()返回- 1時(一個分界符,毋庸置疑,色源於Unix和C) .表示我們已經到達了輸入的末尾。每次read()操作之後,就會將資料輸入到緩衝器中. flip()則是準備緩衝器以便它的資訊可以由write()提取. write()操作之後,資訊仍在緩衝器中,接著clear()操作則對所有的內部指標重新安排,以便緩衝器在另一個read()操作期間能夠做好接受資料的準備。 然而,上面那個程式並不是處理此類操作的理想方式.特殊方法transferTo()和transferFrom()則允許我們將一個通道和另一個通道直接相連:
package com.java.io;import java.io.FileInputStream;import java.io.FileOutputStream;import java.nio.channels.FileChannel;public class TransferTo {      public static void main(String[] args) throws Exception {            if(args.length != 2) {              System.out.println("arguments: sourcefile destfile");              System.exit(1);            }            FileChannel in = new FileInputStream(args[0]).getChannel(),                        out = new FileOutputStream(args[1]).getChannel();                        in.transferTo(0, in.size(), out);            // Or:            // out.transferFrom(in, 0, in.size());      }}
View Code

 

 

1 轉換資料          回過頭看GetChannel.java這個程式就會發現,為了輸出檔案中的資訊,我們必須每次唯讀取一個位元組的資料,然後將每個byte類型強制轉換成char類型。這種方法似乎有點原始-一如果我們查看一下java.nio.CharBuffer這個類,將會發現它有一個toString()方法是這樣定義的: "返回一個包含緩衝器中所有字元的字串。"既然ByteBuffer可以看作是具有asCharBuffer()方法的CharBuffer ,那麼為什麼不用它呢?正如下面的輸出語句中第一行所見,這種方法並不能解決問題:
package com.java.io;import java.io.FileInputStream;import java.io.FileOutputStream;import java.nio.ByteBuffer;import java.nio.channels.FileChannel;import java.nio.charset.Charset;public class BufferToText {    private static final int BSIZE = 1024;        @SuppressWarnings("resource")    public static void main(String[] args) throws Exception {        FileChannel fc = new FileOutputStream("data2.txt").getChannel();        fc.write(ByteBuffer.wrap("Some text".getBytes()));        fc.close();        fc = new FileInputStream("data2.txt").getChannel();        ByteBuffer buff = ByteBuffer.allocate(BSIZE);        fc.read(buff);        buff.flip();        // Doesn‘t work:        System.out.println(buff.asCharBuffer());                // Decode using this system‘s default Charset:        buff.rewind();        String encoding = System.getProperty("file.encoding");        System.out.println("Decoded using " + encoding + ": " + Charset.forName(encoding).decode(buff));                // Or, we could encode with something that will print:        fc = new FileOutputStream("data2.txt").getChannel();        fc.write(ByteBuffer.wrap("Some text".getBytes("UTF-16BE")));        fc.close();        // Now try reading again:        fc = new FileInputStream("data2.txt").getChannel();        buff.clear();        fc.read(buff);        buff.flip();        System.out.println(buff.asCharBuffer());                // Use a CharBuffer to write through:        fc = new FileOutputStream("data2.txt").getChannel();        buff = ByteBuffer.allocate(24); // More than needed        buff.asCharBuffer().put("Some text");        fc.write(buff);        fc.close();                // Read and display:        fc = new FileInputStream("data2.txt").getChannel();        buff.clear();        fc.read(buff);        buff.flip();        System.out.println(buff.asCharBuffer());    }}
View Code緩衝器容納的是普通的位元組,為了把它們轉換成字元,我們要麼在輸入它們的時候對其進行編碼(這樣,它們輸出時才具有意義) .要麼在將其從緩衝器輸出時對它們進行解碼。可以使用java.nio.charset.Charset類實現這些功能,該類提供了把資料編碼成多種不同類型的字元集的工具  

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

---------------

ThinkJava-新IO

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.