<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之旅 廣告
                # Java 通道教程 – NIO 2.0 > 原文: [https://howtodoinjava.com/java7/nio/java-nio-2-0-channels/](https://howtodoinjava.com/java7/nio/java-nio-2-0-channels/) 通道是繼[**緩沖區**](//howtodoinjava.com/java-7/nio/java-nio-2-0-working-with-buffers/ "Java NIO 2.0 : Working With Buffers")之后的`java.nio`的第二項重大創新,我們在我之前的教程中已詳細了解到。 通道提供與 I/O 服務的直接連接。 **通道是一種在字節緩沖區和通道另一端的實體(通常是文件或套接字)之間有效傳輸數據的介質。** 通常,通道與操作系統文件描述符具有一對一的關系。 通道類提供了維持平臺獨立性所需的抽象,但仍可以對現代操作系統的本機 I/O 能力進行建模。 通道是網關,通過它可以以最小的開銷訪問操作系統的本機 I/O 服務,而緩沖區是通道用來發送和接收數據的內部端點。 ## NIO 通道基礎 在層次結構的頂部,有[`Channel`](https://docs.oracle.com/javase/7/docs/api/java/nio/channels/Channel.html "Channel")接口,如下所示: ```java package java.nio.channels; public interface Channel { public boolean isOpen(); public void close() throws IOException; } ``` 由于依賴底層平臺的各種因素,`Channel`實現在操作系統之間存在根本性的差異,因此通道 API(或接口)僅描述了可以完成的工作。 **`Channel`實現通常使用本機代碼執行實際工作。 通過這種方式,通道接口使您能夠以受控且可移植的方式訪問低級 I/O 服務。** 從頂級`Channel`接口可以看到,所有通道只有兩個共同的操作:檢查通道是否打開(`isOpen()`)和關閉打開的通道(`close()`)。 ## 打開通道 眾所周知,I/O 分為兩大類:**文件 I/O 和流 I/O** 。 因此,通道有兩種類型也就不足為奇了:文件和套接字。 `FileChannel`類和`SocketChannel`類用于處理這兩個類別。 僅可以通過在打開的`RandomAccessFile`,`FileInputStream`或`FileOutputStream`對象上調用`getChannel()`方法來獲得`FileChannel`對象。 您不能直接創建`FileChannel`對象。 ```java RandomAccessFile raf = new RandomAccessFile ("somefile", "r"); FileChannel fc = raf.getChannel(); ``` 與`FileChannel`相反,套接字通道具有工廠方法來直接創建新的套接字通道。 例如 ```java //How to open SocketChannel SocketChannel sc = SocketChannel.open(); sc.connect(new InetSocketAddress("somehost", someport)); //How to open ServerSocketChannel ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.socket().bind (new InetSocketAddress (somelocalport)); //How to open DatagramChannel DatagramChannel dc = DatagramChannel.open(); ``` 上面的方法返回一個相應的套接字通道對象。 它們不是`RandomAccessFile.getChannel()`的新通道的來源。 如果已經存在,則它們返回與套接字關聯的通道。 他們從不創造新的渠道。 ## 使用通道 正如我們已經學習到緩沖區的教程一樣,該教程介紹了通道與`ByteBuffer`對象之間的數據傳輸。 大多數讀/寫操作由從下面的接口實現的方法執行。 ```java public interface ReadableByteChannel extends Channel { public int read (ByteBuffer dst) throws IOException; } public interface WritableByteChannel extends Channel { public int write (ByteBuffer src) throws IOException; } public interface ByteChannel extends ReadableByteChannel, WritableByteChannel { } ``` **通道可以是單向或雙向**。 給定的通道類可能實現`ReadableByteChannel`,它定義了`read()`方法。 另一個可能會實現`WritableByteChannel`以提供`write()`。 實現這些接口中的一個或另一個的類是單向的:它只能在一個方向上傳輸數據。 如果一個類實現兩個接口(或擴展兩個接口的`ByteChannel`),則它是雙向的,可以雙向傳輸數據。 如果您查看通道類,則會發現每個文件和套接字通道都實現了這三個接口。 就類定義而言,這意味著所有文件和套接字通道對象都是雙向的。 對于套接字來說,這不是問題,因為它們始終是雙向的,但是對于文件來說,這是一個問題。 從`FileInputStream`對象的`getChannel()`方法獲得的`FileChannel`對象是只讀的,但是在接口聲明方面是雙向的,因為 **`FileChannel`實現了`ByteChannel`** 。 在這樣的通道上調用`write()`會拋出未選中的`NonWritableChannelException`,因為`FileInputStream`總是打開具有只讀權限的文件。 因此,請記住,當通道連接到特定的 I/O 服務時,通道實例的特性將受到與其連接的服務的特性的限制。 連接到只讀文件的`Channel`實例無法寫入,即使該`Channel`實例所屬的類可能具有`write()`方法。 程序員要知道如何打開通道,而不要嘗試執行底層 I/O 服務不允許的操作。 ```java FileInputStream input = new FileInputStream ("readOnlyFile.txt"); FileChannel channel = input.getChannel(); // This will compile but will throw an IOException // because the underlying file is read-only channel.write (buffer); ``` `ByteChannel`的`read()`和`write()`方法將`ByteBuffer`對象作為參數。 每個都返回傳輸的字節數,該字節數可以小于緩沖區中的字節數,甚至為零。 緩沖區的位置將增加相同的量。 如果執行了部分傳輸,則可以將緩沖區重新提交給通道以繼續傳輸數據,并從該處停止傳輸。 重復直到緩沖區的`hasRemaining()`方法返回`false`。 在下面的示例中,我們將數據從一個通道復制到另一個通道(*或從一個文件復制到另一個文件*): ```java import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.ReadableByteChannel; import java.nio.channels.WritableByteChannel; public class ChannelCopyExample { public static void main(String args[]) throws IOException { FileInputStream input = new FileInputStream ("testIn.txt"); ReadableByteChannel source = input.getChannel(); FileOutputStream output = new FileOutputStream ("testOut.txt"); WritableByteChannel dest = output.getChannel(); copyData(source, dest); source.close(); dest.close(); } private static void copyData(ReadableByteChannel src, WritableByteChannel dest) throws IOException { ByteBuffer buffer = ByteBuffer.allocateDirect(16 * 1024); while (src.read(buffer) != -1) { // Prepare the buffer to be drained buffer.flip(); // Make sure that the buffer was fully drained while (buffer.hasRemaining()) { dest.write(buffer); } // Make the buffer empty, ready for filling buffer.clear(); } } } ``` **通道可以在阻塞或非阻塞模式下運行。** 處于非阻塞模式的通道永遠不會使調用線程進入睡眠狀態。 所請求的操作要么立即完成,要么返回結果表明未完成任何操作。 只能將面向流的通道(例如套接字和管道)置于非阻塞模式。 ## 關閉通道 要關閉通道,請使用其`close()`方法。 與緩沖區不同,**通道在關閉**后不能重新使用。 開放通道表示與特定 I/O 服務的特定連接,并封裝了該連接的狀態。 關閉通道后,該連接將丟失,并且該通道不再連接任何東西。 **在通道上多次調用`close()`是沒有害處的。 隨后在關閉通道上對`close()`的調用無濟于事,并立即返回。** 可以想到,套接字通道可能需要大量時間才能關閉,具體取決于系統的網絡實現。 某些網絡協議棧可能會在輸出耗盡時阻止關閉。 通道的打開狀態可以使用`isOpen()`方法進行測試。 如果返回`true`,則可以使用該通道。 如果為`false`,則該通道已關閉,無法再使用。 嘗試讀取,寫入或執行任何其他需要通道處于打開狀態的操作將導致`ClosedChannelException`。 **祝您學習愉快!**
                  <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>

                              哎呀哎呀视频在线观看