Scatter/Gather I/O,翻译过来是分散/聚集 I/O(又称为Vectored I/O)。是一种可以单次调用中对多个缓冲区进行输入/输出的方式,可以把多个缓冲区数据一次写到数据流中,也可以把一个数据流读取到多个缓冲区
使用Scatter/Gather I/O的主要原因是为了高效和方便,可以在一次I/O操作中处理多个Buffer的读写
各种操作系统都提供了Scatter/Gather I/O的函数库,可以很方便的调用。对于一些高级语言,也是有相应实现的。
Java中的实现
Java中也提供了Scatter/Gather I/O的实现,对应的接口为java.nio.channels.ScatteringByteChannel/java.nio.channels.GatheringByteChannel
,都在java的nio包下。
先来看一下接口定义:
public interface ScatteringByteChannel extends ReadableByteChannel
{
public long read (ByteBuffer [] dsts) throws IOException;
public long read (ByteBuffer [] dsts, int offset, int length) throws IOException;
}
public interface GatheringByteChannel extends WritableByteChannel
{
public long write(ByteBuffer[] srcs) throws IOException;
public long write(ByteBuffer[] srcs, int offset, int length) throws IOException;
}
使用也很简单,因为FileChannel/
`SocketChanel是实现了这两个接口的,也就是说使用
FileChannel/SocketChanel`时可以直接使用Scatter/Gather I/O
Java中的使用例子
下面的例子中创建了两个ByteBuyffer,一个ByteBuffer存储一个随机数,另一个ByteBuffer存储一个随机字符串。
第一步,使用GatheringByteChannel
`将两个ByteBuffer中的数据写入至`FileChannel
第二部,使用ScatteringByteChannel
将FileChannel中的数据读取至两个ByteBuffer中
第三步,验证读取后的数据是否匹配
示例代码来源:https://howtodoinjava.com/java/nio/nio-scatter-gather-vectored-io/
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.GatheringByteChannel;
import java.nio.channels.ScatteringByteChannel;
public class ScatteringAndGatheringIOExample
{
public static void main(String params[])
{
String data = "Scattering and Gathering example shown in howtodoinjava.com";
gatherBytes(data);
scatterBytes();
}
/*
* gatherBytes() reads bytes from different buffers and writes to file
* channel. Note that it uses a single write for both the buffers.
*/
public static void gatherBytes(String data)
{
//First Buffer holds a random number
ByteBuffer bufferOne = ByteBuffer.allocate(4);
//Second Buffer holds data we want to write
ByteBuffer buffer2 = ByteBuffer.allocate(200);
//Writing Data sets to Buffer
bufferOne.asIntBuffer().put(13);
buffer2.asCharBuffer().put(data);
//Calls FileOutputStream(file).getChannel()
GatheringByteChannel gatherer = createChannelInstance("test.txt", true);
//Write data to file
try
{
gatherer.write(new ByteBuffer[] { bufferOne, buffer2 });
}
catch (Exception e)
{
e.printStackTrace();
}
}
/*
* scatterBytes() read bytes from a file channel into a set of buffers. Note that
* it uses a single read for both the buffers.
*/
public static void scatterBytes()
{
//First Buffer holds a random number
ByteBuffer bufferOne = ByteBuffer.allocate(4);
//Second Buffer holds data we want to write
ByteBuffer bufferTwo = ByteBuffer.allocate(200);
//Calls FileInputStream(file).getChannel()
ScatteringByteChannel scatterer = createChannelInstance("test.txt", false);
try
{
//Reading from the channel
scatterer.read(new ByteBuffer[] { bufferOne, bufferTwo });
}
catch (Exception e)
{
e.printStackTrace();
}
//Read the buffers seperately
bufferOne.rewind();
bufferTwo.rewind();
int bufferOneContent = bufferOne.asIntBuffer().get();
String bufferTwoContent = bufferTwo.asCharBuffer().toString();
//Verify the content
System.out.println(bufferOneContent);
System.out.println(bufferTwoContent);
}
public static FileChannel createChannelInstance(String file, boolean isOutput)
{
FileChannel fc = null;
try
{
if (isOutput) {
fc = new FileOutputStream(file).getChannel();
} else {
fc = new FileInputStream(file).getChannel();
}
}
catch (Exception e) {
e.printStackTrace();
}
return fc;
}
}
Netty 的实现??
Netty中提供了CompositeByteBuf,虽然看起来类似Scatter/Gather I/O,但和JDK自带的完全不是一回事,Netty只是在Java层面对Buffer进行了组合
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。