矢量IO=Scatter/Gather:
在多个缓冲区上实现一个简单的IO操作。减少或避免了缓冲区拷贝和系统调用(IO)
write:Gather
数据从几个缓冲区顺序抽取并沿着通道发送,就好比全部缓冲区全部连接起来放入一个大的缓冲区进行发送,缓冲区本身不具备gather能力。
read:Scatter
从通道读取的数据会按顺序散布到多个缓冲区,直到缓冲区被填满或者通道数据读完。
Gather:
Scatter:
示例代码
/ **
*散点
* <br> ------------------------------ <br>
* @param fileName
* @throws IOException
* @see FileChannel.read(java.nio.ByteBuffer [])
* /
private static void scatter(final String fileName) throws IOException {
RandomAccessFile accessFile = new RandomAccessFile(fileName, “r” );
//获取文件通道
FileChannel channel = accessFile.getChannel();
//创建两个缓冲区
ByteBuffer headBuffer = ByteBuffer.allocate(2 );
ByteBuffer bodyBuffer = ByteBuffer.allocate(1024 );
ByteBuffer [] allBuffers = new ByteBuffer [] {headBuffer,bodyBuffer};
// headBuffer前10个字节
// bodyBuffer剩下的
long n = channel.read(allBuffers);
System.out.println(“共读到多少字节:” + n);
headBuffer.flip();
// head缓冲区中的数据:qw
System.out.println(“头缓冲区中的数据:” + charset.decode(headBuffer));
bodyBuffer.flip();
// body缓冲区中的数据:ertyuiop
System.out.println(“body缓冲区中的数据:” + charset.decode(bodyBuffer));
accessFile.close();
channel.close();
}
/ **
*散点2
* <br> ------------------------------ <br>
* @param fileName
* @throws IOException
* @see FileChannel.read(java.nio.ByteBuffer [],int,int)
* /
private static void scatter2(final String fileName) throws IOException {
RandomAccessFile accessFile = new RandomAccessFile(fileName, “r” );
//获取文件通道
FileChannel channel = accessFile.getChannel();
//创建五个缓冲区
ByteBuffer headBuffer = ByteBuffer.allocate(2 );
ByteBuffer bodyBuffer1 = ByteBuffer.allocate(3 );
ByteBuffer bodyBuffer2 = ByteBuffer.allocate(2 );
ByteBuffer bodyBuffer3 = ByteBuffer.allocate(2 );
ByteBuffer bodyBuffer4 = ByteBuffer.allocate(1 );
ByteBuffer [] allBuffers = new ByteBuffer [] {
headBuffer,
bodyBuffer1,bodyBuffer2,
bodyBuffer3,bodyBuffer4,};
// 0从那个缓冲区开始被使用使用3个缓冲区
//会使用headBuffer,bodyBuffer1,bodyBuffer2
长 N = channel.read(allBuffers, 0 , 3 );
System.out.println(“共读到多少字节:” + n);
headBuffer.flip();
// head缓冲区中的数据:qw
System.out.println(“头缓冲区中的数据:” + charset.decode(headBuffer));
bodyBuffer1.flip();
// body1缓冲区中的数据:ert
System.out.println(“ body1缓冲区中的数据:” + charset.decode(bodyBuffer1));
bodyBuffer2.flip();
// body2缓冲区中的数据:yu
System.out.println(“body2缓冲区中的数据:” + charset.decode(bodyBuffer2));
bodyBuffer3.flip();
// body3,没有数据
System.out.println(“body3缓冲区中的数据:” + charset.decode(bodyBuffer3));
bodyBuffer4.flip();
// body4没有数据
System.out.println(“body4缓冲区中的数据:” + charset.decode(bodyBuffer4));
accessFile.close();
channel.close();
}
/ **
*
* <br> ------------------------------ <br>
* @param fileName
* @throws IOException
* /
private static void writeData(final String fileName,String data) throws IOException {
RandomAccessFile accessFile = new RandomAccessFile(fileName, “rw” );
accessFile.writeBytes(data);
accessFile.close();
}
private static Charset charset = Charset.forName(“GBK” );
public static void main(String [] args) throws IOException {
final String fileName = “D:/test.log” ;
//先写入10个字节数据以便测试分散模式
writeData(fileName, “qwertyuiop” );
/** - - - - - 分散 - - - - - - */
// read(java.nio.ByteBuffer [])
scatter(fileName);
// read(java.nio.ByteBuffer [],int,int)
scatter2(fileName);
}
/ **
*聚集
* <br> ------------------------------ <br>
* @param fileName
* @throws IOException
* @see FileChannel#write(java.nio.ByteBuffer [])
* /
private static void gather(String fileName) throws IOException {
RandomAccessFile accessFile = new RandomAccessFile(fileName, “rw” );
//获取文件通道
FileChannel channel = accessFile.getChannel();
//创建两个缓冲区
ByteBuffer headBuffer = ByteBuffer.allocate(3 );
headBuffer.put(“abc” .getBytes());
ByteBuffer bodyBuffer = ByteBuffer.allocate(1024 );
bodyBuffer.put(“defg” .getBytes());
ByteBuffer [] allBuffers = new ByteBuffer [] {headBuffer,bodyBuffer};
headBuffer.flip();
bodyBuffer.flip();
//将按ALLBuffers顺序写入abcdefg
long n = channel.write(allBuffers);
System.out.println(“共写入多少字节:” + n);
accessFile.close();
channel.close();
}
/ **
* gather2
* <br> ------------------------------ <br>
* @param fileName
* @throws IOException
* @see FileChannel#write(java.nio.ByteBuffer [],int,int)
* /
private static void collect2(String fileName) throws IOException {
RandomAccessFile accessFile = new RandomAccessFile(fileName, “rw” );
//获取文件通道
FileChannel channel = accessFile.getChannel();
//创建两个缓冲区
ByteBuffer headBuffer = ByteBuffer.allocate(3 );
ByteBuffer bodyBuffer1 = ByteBuffer.allocate(4 );
ByteBuffer bodyBuffer2 = ByteBuffer.allocate(20 );
ByteBuffer bodyBuffer3 = ByteBuffer.allocate(20 );
ByteBuffer bodyBuffer4 = ByteBuffer.allocate(20 );
headBuffer.put(“abc” .getBytes());
bodyBuffer1.put(“defg” .getBytes());
bodyBuffer2.put(“bnbnbnb” .getBytes());
bodyBuffer3.put(“zzz444” .getBytes());
ByteBuffer [] allBuffers = new ByteBuffer [] {
headBuffer,
bodyBuffer1,bodyBuffer2,
bodyBuffer3,bodyBuffer4,};
headBuffer.flip();
bodyBuffer1.flip();
bodyBuffer2.flip();
bodyBuffer3.flip();
bodyBuffer4.flip();
//将按allBuffers数组顺序使用两个缓冲区
// 0从哪开始
// 2使用几个
//当前使用headBuffer bodyBuffer1
//最终写入abcdefg
长 N = channel.write(allBuffers, 0 , 2 );
//应该返回7个字节
System.out.println(“共写入多少字节:” + n);
accessFile.close();
channel.close();
}
private static Charset charset = Charset.forName(“GBK” );
public static void main(String [] args) throws IOException {
final String fileName = “D:/test.log” ;
/** - - - - - 收集 - - - - - - */
// FileChannel#write(java.nio.ByteBuffer [])
gather(fileName);
// FileChannel#write(java.nio.ByteBuffer [],int,int)
gather2(fileName);
}