Java NIO之Scatter和Gather

奇舞移動發表於2018-12-12

前面的文章分享了Buffer和Channel,以及關於Buffer和Channel的基本操作。這篇文章繼續分享關於Channel的Buffer的操作Scatter和Gather,這篇內容比較簡單。

什麼是Scatter和Gather

Scatter和Gather的字面意思就可以分好的解釋他們各自的用途。其中Scatter的意思是分散,Gather的意思是聚集,我們再來看一下他們是如何分散和聚集的,如下圖所示

https://user-gold-cdn.xitu.io/2018/12/12/167a0124c7b94db2?w=329&<br />h=216&<br />f=png&<br />s=10792″ class=”lazyload” data-height=”216″ src=”https://user-gold-cdn.xitu.io/2018/12/12/167a0124c7b94db2?imageView2/0/w/1280/h/960/ignore-error/1″ data-width=”329″><figcaption></figcaption></figure>
</p>
<p>當一個Channel中的資料被多個Buffer來處理,就是分散也就是Scatter。</p>
</p>
<figure><img alt=h=216&
f=png&
s=10867″ class=”lazyload” data-height=”216″ src=”https://user-gold-cdn.xitu.io/2018/12/12/167a0124c7cce270?imageView2/0/w/1280/h/960/ignore-error/1″ data-width=”329″>

當多個Buffer同時向一個Channel中寫資料時,就是聚集也就是Gather。

如何使用

我們用FileChannel來解釋如何使用Scatter和Gather。

Gather

RandomAccessFile randomAccessFile = new RandomAccessFile(  "/Users/yangpeng/Documents/360/code/QiwooSample/NIOSample/src/com/nio/sample/file.txt", "rw");
randomAccessFile.seek(0);
FileChannel fileChannel = randomAccessFile.getChannel();
System.out.println("FileChannel position " + fileChannel.position());
ByteBuffer buffer = ByteBuffer.allocate(100);
String str = "hello";
buffer.clear();
buffer.put(str.getBytes());
buffer.flip();
ByteBuffer buffer2 = ByteBuffer.allocate(100);
String str2 = " world";
buffer2.clear();
buffer2.put(str2.getBytes());
buffer2.flip();
ByteBuffer[] bufferArray = {
buffer, buffer2
};
fileChannel.write(bufferArray);
randomAccessFile.close();
fileChannel.close();
複製程式碼
  • 通過RandomAccessFile獲得一個FileChannel
  • 分別初始化兩個ByteBuffer,裡面分別放入”hello”和”world”兩個字串。
  • 初始化一個ByteBuffer陣列,內容為第二步的兩個Buffer
  • 把ByteBuffer陣列裡的內容寫入到FileChannel
  • 關閉RandomAccessFile和FileChannel

執行完以上幾步之後,我們開啟檔案檢視就是文字里的內容就是”hello world”

注意:寫入的是緩衝區position和limit之間的資料。如果一個緩衝區容量為10位元組,但是僅有5位元組的資料,那麼寫入到通道中的資料就是5個位元組。

Scatter

RandomAccessFile randomAccessFile = new RandomAccessFile(  "/Users/yangpeng/Documents/360/code/QiwooSample/NIOSample/src/com/nio/sample/file.txt", "rw");
randomAccessFile.seek(0);
FileChannel fileChannel = randomAccessFile.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(5);
ByteBuffer buffer2 = ByteBuffer.allocate(100);
ByteBuffer[] bufferArray = {buffer, buffer2
};
fileChannel.read(bufferArray);
buffer.flip();
while (buffer.hasRemaining()) {
System.out.print((char) buffer.get());

}System.out.println("");
buffer2.flip();
while (buffer2.hasRemaining()) {
System.out.print((char) buffer2.get());

}randomAccessFile.close();
fileChannel.close();
複製程式碼
  • 通過RandomAccessFile獲得一個FileChannel
  • 分別初始化兩個ByteBuffer,準備把資料讀到這兩個buffer裡
  • 初始化一個ByteBuffer陣列,內容為第二步的兩個Buffer
  • 從FileChannel中讀出資料然後寫入到ByteBuffer中
  • 關閉RandomAccessFile和FileChannel

執行完以上幾步之後,輸出的內容就是”hello world”

注意:read()方法根據緩衝區陣列中的順序將channel資料寫入。一個緩衝區寫滿後,再往下一個緩衝區寫。

使用場景

適用於寫入或者讀出的資料是固定大小的幾部分。

關注微信公眾號,最新技術乾貨實時推送

image

來源:https://juejin.im/post/5c1066fd5188250e8465a1ad

相關文章