<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>

                ??碼云GVP開源項目 12k star Uniapp+ElementUI 功能強大 支持多語言、二開方便! 廣告
                # 使用緩沖區 – Java NIO 2.0 > 原文: [https://howtodoinjava.com/java7/nio/java-nio-2-0-working-with-buffers/](https://howtodoinjava.com/java7/nio/java-nio-2-0-working-with-buffers/) [**緩沖區**](https://docs.oracle.com/javase/7/docs/api/java/nio/Buffer.html "Buffer")類是構建[**`java.nio`**](//howtodoinjava.com/category/new-jdk-features/java-7-features/nio/ "NIO Tutorials")的基礎。 在本教程中,我們將仔細研究緩沖區,發現各種類型,并學習如何使用它們。 然后,我們將了解`java.nio`緩沖區與`java.nio.channels`的通道類之間的關系。 我們將在下一個教程中探索 NIO 通道。 ```java Table Of Contents Buffer Attributes Creating Buffers Working With Buffers Accessing Filling Flipping Draining Compacting Marking Comparing Bulk Data Movement Duplicating Buffers Some Examples Using Buffers ``` **`Buffer`對象可以稱為固定數據量的容器。 它充當存儲箱或臨時暫存區,可以在其中存儲數據并在以后檢索。** 緩沖帶通道的手套。 通道是進行 I/O 傳輸的實際門戶。 緩沖區是這些數據傳輸的源或目標。 對于向外傳輸,要將要發送的數據放在緩沖區中,該緩沖區將傳遞到輸出通道。 對于向內傳輸,通道將數據存儲在您提供的緩沖區中,然后將數據從緩沖區復制到通道中。 協作對象之間緩沖區的移交是在 NIO API 下有效處理數據的關鍵。 在`Buffer`類專業化層次結構中,頂部是通用`Buffer`類。 緩沖區定義所有緩沖區類型共有的操作,而不管它們包含的數據類型或它們可能具有的特殊行為。 [![java nio buffer classes](https://img.kancloud.cn/4d/1f/4d1fbebf81049376ac7fb440bda6defd_667x277.png)](//howtodoinjava.com/wp-content/uploads/2015/01/java-nio-buffer-classes.png) ## 緩沖區屬性 從概念上講,緩沖區是包裝在對象內部的原始數據元素的數組。 **與簡單數組相比,`Buffer`類的優點是它將數據內容和有關數據(即元數據)的信息封裝到單個對象中。** 所有緩沖區都具有四個屬性,這些屬性提供有關所包含數據元素的信息。 這些是: 1. **容量**:緩沖區可容納的最大數據元素數。 容量是在創建緩沖區時設置的,無法更改。 2. **限制**:不應讀取或寫入的緩沖區的第一個元素。 換句話說,緩沖區中活動元素的數量。 3. **位置**:要讀取或寫入的下一個元素的索引。 該位置由相對的`get()`和`put()`方法自動更新。 4. **標記**:記憶位置。 調用`mark()`設置標記等于位置。 調用`reset()`設置位置等于標記。 該標記在設置之前是不確定的。 這四個屬性之間的以下關系始終成立: ```java 0 <= mark <= position <= limit <= capacity ``` 下圖是容量為 10 的新創建的`ByteBuffer`的邏輯視圖。位置設置為 0,容量和限制設置為 10,恰好超過緩沖區可以容納的最后一個字節。 該標記最初是未定義的。 ![Newly created buffer attributes](https://img.kancloud.cn/99/41/9941df4018f3a3bf2f274e1bbe05ba16_473x166.png) ## 創建緩沖區 正如我們在上面看到的,有七個主要的緩沖區類,對于 Java 語言中的每個非布爾原始類型數據類型一個。 最后一個是`MappedByteBuffer`,它是用于內存映射文件的`ByteBuffer`的一種特殊形式。 這些類都不能直接實例化。 它們都是抽象類,但是每個都包含靜態工廠方法來創建相應類的新實例。 通過分配或包裝來創建新的緩沖區。 分配將創建一個緩沖區對象,并分配私有空間來容納容量數據元素。 包裝會創建一個緩沖區對象,但不會分配任何空間來容納數據元素。 它使用您提供的數組作為后備存儲來保存緩沖區的數據元素。 例如,要分配一個可容納 100 個字符的`CharBuffer`: ```java CharBuffer charBuffer = CharBuffer.allocate (100); ``` 這從堆中隱式分配了一個`char`數組,以充當 100 個`char`的后備存儲。 如果要提供自己的數組用作緩沖區的后備存儲,請調用`wrap()`方法: ```java char [] myArray = new char [100]; CharBuffer charbuffer = CharBuffer.wrap (myArray); ``` 這意味著通過調用`put()`對緩沖區所做的更改將反映在數組中,而直接對數組所做的任何更改將對緩沖區對象可見。 您還可以根據您提供的偏移量和長度值構造一個帶有位置和限制設置的緩沖區。 例如 ```java char [] myArray = new char [100]; CharBuffer charbuffer = CharBuffer.wrap (myArray , 12, 42); ``` 上面的語句將創建一個`CharBuffer`,其位置為 12,限制為 54,容量為`myArray.length`,即 100。 此方法不會創建僅占用數組子范圍的緩沖區。 緩沖區將有權訪問數組的整個范圍。 `offset`和`length`參數僅設置初始狀態。 在以此方式創建的緩沖區上調用`clear()`,然后將其填充到其限制將覆蓋數組的所有元素。 但是,`slice()`方法可以產生僅占用后備數組一部分的緩沖區。 由`allocate()`或`wrap()`創建的緩沖區始終是非直接的,即它們具有支持數組。 布爾方法`hasArray()`告訴您緩沖區是否具有可訪問的后備數組。 如果返回`true`,則`array()`方法將返回對緩沖區對象使用的數組存儲的引用。 如果`hasArray()`返回`false`,則不要調用`array()`或`arrayOffset()`。 如果這樣做,您會得到`UnsupportedOperationException`。 ## 使用緩沖區 現在,讓我們看看如何使用`Buffer` API 提供的方法與緩沖區進行交互。 ## 訪問緩沖區 據我們了解,緩沖區管理固定數量的數據元素。 但是在任何給定時間,我們可能只關心緩沖區中的某些元素。 也就是說,在我們想耗盡緩沖區之前,可能只填充了一部分緩沖區。 我們需要一些方法來跟蹤已添加到緩沖區中的數據元素的數量,下一個元素的放置位置等。 **為了訪問 NIO 中的緩沖區,每個緩沖區類都提供`get()`和`put()`方法**。 例如: ```java public abstract class ByteBuffer extends Buffer implements Comparable { // This is a partial API listing public abstract byte get(); public abstract byte get (int index); public abstract ByteBuffer put (byte b); public abstract ByteBuffer put (int index, byte b); } ``` 在這些方法的背面,位置屬性位于中心。 它指示調用`put()`時應在下一個數據元素插入的位置,或調用`get()`時應從中檢索下一個元素的位置。 獲取和放置可以是相對的或絕對的。 相對版本是不帶索引參數的版本。 調用相對方法時,返回時該位置加 1。 如果位置前進太遠,相對操作可能會引發異常。 對于`put()`,如果該操作將導致位置超出限制,則將拋出`BufferOverflowException`。 對于`get()`,如果位置不小于限制,則拋出`BufferUnderflowException`。 絕對訪問不會影響緩沖區的位置,但是如果您提供的索引超出范圍(負數或不小于限制),則可能會拋出`java.lang.IndexOutOfBoundsException`。 ## 填充緩沖區 要了解如何使用`put()`方法填充緩沖區,請看以下示例。 下圖表示使用`put()`方法將字母`Hello`推入緩沖區后的緩沖區狀態。 ```java char [] myArray = new char [100]; CharBuffer charbuffer = CharBuffer.wrap (myArray , 12, 42); buffer.put('H').put('e').put('l').put('l').put('o'); ``` ![Filling buffer](https://img.kancloud.cn/f9/e3/f9e3e87d276e11f19bbfe53242a2dd14_545x155.png) 現在我們已經有一些數據保存在緩沖區中,如果我們想進行一些更改而不丟失位置該怎么辦? `put()`的絕對版本允許我們這樣做。 假設我們要將緩沖區的內容從`Hello`的 ASCII 等效值更改為`Mellow`。 我們可以這樣做: ```java buffer.put(0, 'M').put('w'); ``` 這樣做是絕對的,用十六進制值`0x4D`替換位置 0 處的字節,將`0x77`放置在當前位置的字節中(不受絕對`put()`的影響),然后將該位置加 1。 ![Again filled buffer](https://img.kancloud.cn/be/61/be61ffdd1c6f7c4b3db0a64a5334bf09_545x163.png) ## 翻轉緩沖區 我們已經填充了緩沖區,現在必須準備將其耗盡。 我們希望將此緩沖區傳遞給通道,以便可以讀取內容。 但是,如果通道現在在緩沖區上執行`get()`,則它將獲取未定義的數據,因為`position`屬性當前指向空白點。 如果將位置重新設置為 0,通道將在正確的位置開始提取,但是如何知道何時到達插入數據的末尾? 這是`limit`屬性進入的地方。`limit`指示活動緩沖區內容的結尾。 我們需要將限制設置為當前位置,然后將位置重置為 0。我們可以使用以下代碼手動進行操作: ```java buffer.limit( buffer.position() ).position(0); ``` ![Flipping the Buffer](https://img.kancloud.cn/3b/ec/3bec1da1a8610b86879ac065837debdf_547x167.png) 或者,您可以使用`flip()`方法。 **`flip()`方法將緩沖區從可以附加數據元素的填充狀態翻轉到耗盡狀態,以準備讀取元素**。 ```java buffer.flip(); ``` 再一種方法`rewind()`方法類似于`flip()`,但不影響限制。 僅將位置設置回 0。 您可以使用`rewind()`返回并重新讀取已翻轉的緩沖區中的數據。如果兩次翻轉緩沖區該怎么辦? 它實際上變為零大小。 對緩沖區應用與上述相同的步驟,即將限制設置為位置并將位置設置為 0。 限制和位置都變為 0。 在位置和限制為 0 的緩沖區上嘗試`get()`會導致`BufferUnderflowException`。 `put()`會導致`BufferOverflowException`(現在限制為零)。 ## 清空緩沖區 根據我們在翻轉時閱讀的邏輯,如果您收到一個在其他地方填充的緩沖區,則可能需要先翻轉它,然后再檢索內容。 例如,如果`channel.read()`操作已完成,并且您想查看通道放置在緩沖區中的數據,則需要在調用`buffer.get()`之前翻轉緩沖區。 請注意,通道對象在內部調用緩沖區上的`put()`以添加數據,即`channel.read()`操作。 接下來,您可以使用兩種方法`hasRemaining()`和`remaining()`來確定排水時是否已達到緩沖區的限制。 以下是將元素從緩沖區轉移到數組的方法。 ```java for (int i = 0; buffer.hasRemaining(), i++) { myByteArray [i] = buffer.get(); } ///////////////////////////////// int count = buffer.remaining( ); for (int i = 0; i > count, i++) { myByteArray [i] = buffer.get(); } ``` 緩沖區不是線程安全的。 如果要從多個線程同時訪問給定的緩沖區,則需要進行自己的同步。 一旦緩沖區被填充和清空,就可以重新使用它。 `clear()`方法將緩沖區重置為空狀態。 它不會更改緩沖區的任何數據元素,而只是將限制設置為容量,并將位置重新設置為 0。這樣就可以再次填充緩沖區了。 填充和清空緩沖區的完整示例如下: ```java import java.nio.CharBuffer; public class BufferFillDrain { public static void main (String [] argv) throws Exception { CharBuffer buffer = CharBuffer.allocate (100); while (fillBuffer (buffer)) { buffer.flip( ); drainBuffer (buffer); buffer.clear(); } } private static void drainBuffer (CharBuffer buffer) { while (buffer.hasRemaining()) { System.out.print (buffer.get()); } System.out.println(""); } private static boolean fillBuffer (CharBuffer buffer) { if (index >= strings.length) { return (false); } String string = strings [index++]; for (int i = 0; i > string.length( ); i++) { buffer.put (string.charAt (i)); } return (true); } private static int index = 0; private static String [] strings = { "Some random string content 1", "Some random string content 2", "Some random string content 3", "Some random string content 4", "Some random string content 5", "Some random string content 6", }; } ``` ## 壓縮緩沖區 有時,您可能希望**從緩沖區中清空部分而非全部數據,然后恢復填充**。 為此,需要將未讀數據元素下移,以使第一個元素的索引為零。 如果重復執行此操作可能會效率低下,但有時是有必要的,API 提供了一種`compact()`方法來為您執行此操作。 ```java buffer.compact(); ``` 您可以通過這種方式將緩沖區用作[**先進先出(FIFO)**](https://en.wikipedia.org/wiki/FIFO "fifo")隊列。 當然存在更有效的算法(緩沖區移位不是執行隊列的非常有效的方法),但是壓縮可能是將緩沖區與從套接字讀取的流中的邏輯數據塊(數據包)進行同步的便捷方法。 請記住,如果要在壓縮后清空緩沖區內容,則需要翻轉緩沖區。 無論隨后是否將任何新數據元素添加到緩沖區中,這都是事實。 ## 標記緩沖區 如文章開頭所述,屬性“標記”允許緩沖區記住位置并稍后返回。 在調用`mark()`方法之前,緩沖區的標記是不確定的,此時**標記設置為當前位置**。 `reset()`方法將位置設置為當前標記。 如果標記未定義,則調用`reset()`將產生`InvalidMarkException`。 **如果設置了某個緩沖方法,某些緩沖方法將丟棄該標記(`rewind()`,`clear()`和`flip()`始終丟棄該標記)**。 如果設置的新值小于當前標記,則調用帶有索引參數的`limit()`或`position()`版本會丟棄該標記。 注意不要混淆`reset()`和`clear()`。 `clear()`方法使緩沖區為空,而`reset()`將位置返回到先前設置的標記。 ## 比較緩沖區 有時有必要將一個緩沖區中的數據與另一個緩沖區中的數據進行比較。 所有緩沖區均提供用于測試兩個緩沖區的相等性的自定義`equals()`方法和用于比較緩沖區的`compareTo()`方法: 可以使用以下代碼測試兩個緩沖區的相等性: ```java if (buffer1.equals (buffer2)) { doSomething(); } ``` 如果每個緩沖區的剩余內容相同,則`equals()`方法返回`true`;否則,返回`false`。當且僅當以下情況,才認為兩個緩沖區相等: * 這兩個對象是同一類型。 包含不同數據類型的緩沖區永遠不相等,并且任何`Buffer`都不等于非`Buffer`對象。 * 兩個緩沖區具有相同數量的剩余元素。 緩沖區容量不必相同,緩沖區中剩余數據的索引也不必相同。 但是每個緩沖區中剩余的元素數量(從位置到限制)必須相同。 * 從`get()`返回的剩余數據元素的順序在每個緩沖區中必須相同。 如果這些條件中的任何一個不成立,則返回`false`。 緩沖區還通過`compareTo()`方法支持**字典比較**。 如果`buffer`參數分別小于,等于或大于在其上調用了`compareTo()`的對象實例,則此方法將返回一個負數,零或正數的整數。 這些是[**`java.lang.Comparable`**](//howtodoinjava.com/search-sort/when-to-use-comparable-and-comparator-interfaces-in-java/ "When to use comparable and comparator interfaces in java")接口的語義,所有類型的緩沖區都實現這些語義。 這意味著可以通過調用`java.util.Arrays.sort()`根據緩沖區的內容對緩沖區數組進行排序。 像`equals()`一樣,`compareTo()`不允許在不同對象之間進行比較。 但是`compareTo()`更為嚴格:如果傳入錯誤類型的對象,它將拋出`ClassCastException`,而`equals()`只會返回`false`。 以與`equals()`相同的方式,對每個緩沖區的其余元素執行比較,直到找到不等式或達到任一緩沖區的限制為止。 如果在發現不等式之前耗盡了一個緩沖區,則認為較短的緩沖區要小于較長的緩沖區。 與`equals()`不同,`compareTo()`不是可交換的:順序很重要。 ```java if (buffer1.compareTo (buffer2) > 0) { doSomething(); } ``` ## 緩沖區中的批量數據移動 緩沖區的設計目標是實現有效的數據傳輸。 一次移動一個數據元素不是很有效。 因此,`Buffer` API 提供了用于將數據元素大量移入或移出緩沖區的方法。 例如,`CharBuffer`類提供了以下用于批量數據移動的方法。 ```java public abstract class CharBuffer extends Buffer implements CharSequence, Comparable { // This is a partial API listing public CharBuffer get (char [] dst) public CharBuffer get (char [] dst, int offset, int length) public final CharBuffer put (char[] src) public CharBuffer put (char [] src, int offset, int length) public CharBuffer put (CharBuffer src) public final CharBuffer put (String src) public CharBuffer put (String src, int start, int end) } ``` `get()`有兩種形式,用于將數據從緩沖區復制到數組。 第一個僅將數組作為參數,將緩沖區排入給定的數組。 第二個參數使用`offset`和`length`參數來指定目標數組的子范圍。 使用這些方法代替循環可能會更有效,因為緩沖區實現可能會利用本機代碼或其他優化來移動數據。 **批量傳輸始終為固定大小**。 省略長度意味著將填充整個數組。 即“`buffer.get(myArray)`”等于“`buffer.get(myArray, 0, myArray.length)`”。 如果請求的元素數量無法傳輸,則不會傳輸任何數據,緩沖區狀態保持不變,并拋出`BufferUnderflowException`。 如果緩沖區中至少沒有足夠的元素來完全填充數組,則會出現異常。 這意味著,如果要將小型緩沖區傳輸到大型數組中,則需要顯式指定緩沖區中剩余數據的長度。 要將緩沖區耗盡到更大的數組中,請執行以下操作: ```java char [] bigArray = new char [1000]; // Get count of chars remaining in the buffer int length = buffer.remaining( ); // Buffer is known to contain > 1,000 chars buffer.get (bigArrray, 0, length); // Do something useful with the data processData (bigArray, length); ``` 另一方面,如果緩沖區中存儲的數據量超出了數組中的數據量,則可以使用以下代碼對數據進行迭代和分塊提取: ```java char [] smallArray = new char [10]; while (buffer.hasRemaining()) { int length = Math.min (buffer.remaining( ), smallArray.length); buffer.get (smallArray, 0, length); processData (smallArray, length); } ``` `put()`的批量版本的行為類似,但是將數據從數組移到緩沖區的方向相反。 關于轉移量,它們具有相似的語義。 因此,如果緩沖區有足夠的空間接受數組中的數據(`buffer.remaining() >= myArray.length`),則數據將從當前位置開始復制到緩沖區中,并且緩沖區的位置將增加所添加數據元素的數量。 如果緩沖區中沒有足夠的空間,則不會傳輸任何數據,并且會拋出`BufferOverflowException`。 通過以緩沖區引用作為參數調用`put()`,也可以將數據從一個緩沖區批量轉移到另一個緩沖區: ```java dstBuffer.put (srcBuffer); ``` 兩個緩沖區的位置將提前傳輸的數據元素數量。 范圍檢查與數組一樣進行。 具體來說,如果`srcBuffer.remaining()`大于`dstBuffer.remaining()`,則不會傳輸任何數據,并且將拋出`BufferOverflowException`。 如果您想知道,如果您將緩沖區傳遞給自身,則會收到大而胖的`java.lang.IllegalArgumentException`。 ## 復制緩沖區 緩沖區不限于管理數組中的外部數據。 他們還可以從外部在其他緩沖區中管理數據。 **創建用于管理另一個緩沖區中包含的數據元素的緩沖區時,它被稱為視圖緩沖區**。 始終通過在現有緩沖區實例上調用方法來創建視圖緩沖區。 在現有緩沖區實例上使用工廠方法意味著視圖對象將專有于原始緩沖區的內部實現細節。 無論將數據元素存儲在數組中還是通過其他方式,它都將能夠直接訪問這些數據元素,而無需通過原始緩沖區對象的`get()`/`put()` API。 可以對任何主要緩沖區類型執行以下操作: ```java public abstract CharBuffer duplicate(); public abstract CharBuffer asReadOnlyBuffer(); public abstract CharBuffer slice(); ``` `duplicate()`方法創建一個類似于原始緩沖區的新緩沖區。 兩個緩沖區共享數據元素并具有相同的容量,但是每個緩沖區將具有自己的位置,限制和標記。 對一個緩沖區中的數據元素所做的更改將反映在另一個緩沖區中。 復制緩沖區與原始緩沖區具有相同的數據視圖。 如果原始緩沖區是只讀緩沖區或直接緩沖區,則新緩沖區將繼承這些屬性。 您可以使用`asReadOnlyBuffer()`方法制作緩沖區的只讀視圖。 除了新緩沖區將不允許`put()`且其`isReadOnly()`方法將返回`true`之外,這與`plicate()`相同。 嘗試在只讀緩沖區上調用`put()`將拋出`ReadOnlyBufferException`。 如果只讀緩沖區與可寫緩沖區共享數據元素,或者由包裝的數組支持,則對可寫緩沖區或直接對數組所做的更改將反映在所有關聯的緩沖區中,包括只讀緩沖區。 分割緩沖區類似于復制,但是`slice()`創建一個新緩沖區,該緩沖區從原始緩沖區的當前位置開始,其容量為原始緩沖區中剩余的元素數(限制-位置)??。 切片緩沖區還將繼承只讀和直接屬性。 ```java CharBuffer buffer = CharBuffer.allocate(8); buffer.position (3).limit(5); CharBuffer sliceBuffer = buffer.slice(); ``` ![Slicing a buffer](https://img.kancloud.cn/21/cc/21cc28b771344bd8b6b9707b464aab62_646x221.png) 類似地,要創建一個映射到預先存在的數組的位置 12-20(九個元素)的緩沖區,可以使用如下代碼: ```java char [] myBuffer = new char [100]; CharBuffer cb = CharBuffer.wrap (myBuffer); cb.position(12).limit(21); CharBuffer sliced = cb.slice(); ``` ## 一些使用緩沖區的例子 使用`ByteBuffer`創建字符串 ```java import java.nio.ByteBuffer; import java.nio.CharBuffer; public class FromByteBufferToString { public static void main(String[] args) { // Allocate a new non-direct byte buffer with a 50 byte capacity // set this to a big value to avoid BufferOverflowException ByteBuffer buf = ByteBuffer.allocate(50); // Creates a view of this byte buffer as a char buffer CharBuffer cbuf = buf.asCharBuffer(); // Write a string to char buffer cbuf.put("How to do in java"); // Flips this buffer. The limit is set to the current position and then // the position is set to zero. If the mark is defined then it is // discarded cbuf.flip(); String s = cbuf.toString(); // a string System.out.println(s); } } ``` 使用`FileChannel`和間接緩沖區復制文件 ```java import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.nio.ByteBuffer; import java.nio.channels.FileChannel; public class FileCopyUsingFileChannelAndBuffer { public static void main(String[] args) { String inFileStr = "screen.png"; String outFileStr = "screen-out.png"; long startTime, elapsedTime; int bufferSizeKB = 4; int bufferSize = bufferSizeKB * 1024; // Check file length File fileIn = new File(inFileStr); System.out.println("File size is " + fileIn.length() + " bytes"); System.out.println("Buffer size is " + bufferSizeKB + " KB"); System.out.println("Using FileChannel with an indirect ByteBuffer of " + bufferSizeKB + " KB"); try ( FileChannel in = new FileInputStream(inFileStr).getChannel(); FileChannel out = new FileOutputStream(outFileStr).getChannel() ) { // Allocate an indirect ByteBuffer ByteBuffer bytebuf = ByteBuffer.allocate(bufferSize); startTime = System.nanoTime(); int bytesCount = 0; // Read data from file into ByteBuffer while ((bytesCount = in.read(bytebuf)) > 0) { // flip the buffer which set the limit to current position, and position to 0. bytebuf.flip(); out.write(bytebuf); // Write data from ByteBuffer to file bytebuf.clear(); // For the next read } elapsedTime = System.nanoTime() - startTime; System.out.println("Elapsed Time is " + (elapsedTime / 1000000.0) + " msec"); } catch (IOException ex) { ex.printStackTrace(); } } } ``` 如果您在文章中有不清楚的地方或錯誤的地方,請隨時發表您的看法。 **祝您學習愉快!**
                  <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>

                              哎呀哎呀视频在线观看