<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ThinkChat2.0新版上線,更智能更精彩,支持會話、畫圖、視頻、閱讀、搜索等,送10W Token,即刻開啟你的AI之旅 廣告
                <!-- ByteBufferS --> ## ByteBuffer 有且僅有 **ByteBuffer**(字節緩沖區,保存原始字節的緩沖區)這一類型可直接與通道交互。查看 `java.nio.`**ByteBuffer** 的 JDK 文檔,你會發現它是相當基礎的:通過初始化某個大小的存儲空間,再使用一些方法以原始字節形式或原始數據類型來放置和獲取數據。但是我們無法直接存放對象,即使是最基本的 **String** 類型數據。這是一個相當底層的操作,也正因如此,使得它與大多數操作系統的映射更加高效。 舊式 I/O 中的三個類分別被更新成 **FileChannel**(文件通道),分別是:**FileInputStream**、**FileOutputStream**,以及用于讀寫的 **RandomAccessFile** 類。 注意,這些都是符合底層 **NIO** 特性的字節操作流。 另外,還有 **Reader** 和 **Writer** 字符模式的類是不產生通道的。但 `java.nio.channels.`**Channels** 類具有從通道中生成 **Reader** 和 **Writer** 的實用方法。 下面來練習上述三種類型的流生成可讀、可寫、可讀/寫的通道: ```java // (c)2017 MindView LLC: see Copyright.txt // 我們不保證這段代碼用于其他用途時是否有效 // 訪問 http://OnJava8.com 了解更多信息 // 從流中獲取通道 import java.nio.*; import java.nio.channels.*; import java.io.*; public class GetChannel { private static String name = "data.txt"; private static final int BSIZE = 1024; public static void main(String[] args) { // 寫入一個文件: try( FileChannel fc = new FileOutputStream(name) .getChannel() ) { fc.write(ByteBuffer .wrap("Some text ".getBytes())); } catch(IOException e) { throw new RuntimeException(e); } // 在文件尾添加: try( FileChannel fc = new RandomAccessFile( name, "rw").getChannel() ) { fc.position(fc.size()); // 移動到結尾 fc.write(ByteBuffer .wrap("Some more".getBytes())); } catch(IOException e) { throw new RuntimeException(e); } // 讀取文件e: try( FileChannel fc = new FileInputStream(name) .getChannel() ) { ByteBuffer buff = ByteBuffer.allocate(BSIZE); fc.read(buff); buff.flip(); while(buff.hasRemaining()) System.out.write(buff.get()); } catch(IOException e) { throw new RuntimeException(e); } System.out.flush(); } } ``` 輸出結果: ``` Some text Some more ``` 我們這里所講的任何流類,都可以通過調用 `getChannel( )` 方法生成一個 **FileChannel**(文件通道)。**FileChannel** 的操作相當基礎:操作 **ByteBuffer** 來用于讀寫,并獨占式訪問和鎖定文件區域(稍后將對此進行描述)。 將字節放入 **ByteBuffer** 的一種方法是直接調用 `put()` 方法將一個或多個字節放入 **ByteBuffer**;當然也可以是其它基本類型的數據。此外,參考上例,我們還可以調用 `wrap()` 方法包裝現有字節數組到 **ByteBuffer**。執行此操作時,不會復制底層數組,而是將其用作生成的 **ByteBuffer** 存儲。這樣產生的 **ByteBuffer** 是數組“支持”的。 data.txt 文件被 **RandomAccessFile** 重新打開。**注意**,你可以在文件中移動 **FileChanne**。 在這里,它被移動到末尾,以便添加額外的寫操作。 對于只讀訪問,必須使用靜態 `allocate()` 方法顯式地分配 **ByteBuffer**。**NIO** 的目標是快速移動大量數據,因此 **ByteBuffer** 的大小應該很重要 —— 實際上,這里設置的 1K 都可能偏小了(我們在工作中應該反復測試以找到最佳大小)。 通過使用 `allocateDirect()` 而不是 `allocate()` 來生成與操作系統具備更高耦合度的“直接”緩沖區,也有可能獲得更高的速度。然而,這種分配的開銷更大,而且實際效果因操作系統的不同而有所不同,因此,在工作中你必須再次測試程序,以檢驗直接緩沖區是否能為你帶來速度上的優勢。 一旦調用 **FileChannel** 類的 `read()` 方法將字節數據存儲到 **ByteBuffer** 中,你還必須調用緩沖區上的 `flip()` 方法來準備好提取字節(這聽起來有點粗糙,實際上這已是非常低層的操作,且為了達到最高速度)。如果要進一步調用 `read()` 來使用 **ByteBuffer** ,還需要每次 `clear()` 來準備緩沖區。下面是個簡單的代碼示例: ```java // newio/ChannelCopy.java // 使用 channels and buffers 移動文件 // {java ChannelCopy ChannelCopy.java test.txt} import java.nio.*; import java.nio.channels.*; import java.io.*; public class ChannelCopy { private static final int BSIZE = 1024; public static void main(String[] args) { if(args.length != 2) { System.out.println( "arguments: sourcefile destfile"); System.exit(1); } try( FileChannel in = new FileInputStream( args[0]).getChannel(); FileChannel out = new FileOutputStream( args[1]).getChannel() ) { ByteBuffer buffer = ByteBuffer.allocate(BSIZE); while(in.read(buffer) != -1) { buffer.flip(); // 準備寫入 out.write(buffer); buffer.clear(); // 準備讀取 } } catch(IOException e) { throw new RuntimeException(e); } } } ``` **第一個FileChannel** 用于讀取;**第二個FileChannel** 用于寫入。當 **ByteBuffer** 分配好存儲,調用 **FileChannel** 的 `read()` 方法返回 **-1**(毫無疑問,這是來源于 Unix 和 C 語言)時,說明輸入流讀取完了。在每次 `read()` 將數據放入緩沖區之后,`flip()` 都會準備好緩沖區,以便 `write()` 提取它的信息。在 `write()` 之后,數據仍然在緩沖區中,我們需要 `clear()` 來重置所有內部指針,以便在下一次 `read()` 中接受數據。 但是,上例并不是處理這種操作的理想方法。方法 `transferTo()` 和 `transferFrom()` 允許你直接連接此通道到彼通道: ```java // newio/TransferTo.java // 使用 transferTo() 在通道間傳輸 // {java TransferTo TransferTo.java TransferTo.txt} import java.nio.channels.*; import java.io.*; public class TransferTo { public static void main(String[] args) { if(args.length != 2) { System.out.println( "arguments: sourcefile destfile"); System.exit(1); } try( FileChannel in = new FileInputStream( args[0]).getChannel(); FileChannel out = new FileOutputStream( args[1]).getChannel() ) { in.transferTo(0, in.size(), out); // Or: // out.transferFrom(in, 0, in.size()); } catch(IOException e) { throw new RuntimeException(e); } } } ``` 可能不會經常用到,但知道這一點很好。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看