我现在正在学习Java NIO,我找到了一个示例来说明FileChannel的收集操作,如下所示:
public class ScattingAndGather {
public static void main(String args[]) {
gather();
}
public static void gather() {
ByteBuffer header = ByteBuffer.allocate(10);
ByteBuffer body = ByteBuffer.allocate(10);
byte[] b1 = { '0', '1' };
byte[] b2 = { '2', '3' };
header.put(b1);
body.put(b2);
ByteBuffer[] buffs = { header, body };
FileOutputStream os = null;
FileChannel channel = null;
try {
os = new FileOutputStream("d:/scattingAndGather.txt");
channel = os.getChannel();
channel.write(buffs);
} catch (IOException e) {
e.printStackTrace();
} finally {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (channel != null) {
try {
channel.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}
虽然结果表明文件已经创建,但是它是空的,应该是0123,这个例子有什么问题?
答案 0 :(得分:2)
出现问题的原因是您从未重置缓冲区的位置。
创建两个ByteBuffer
对象时,它们都从零位置开始。每当您向其中添加内容时,它们的位置都会提高,这意味着当您尝试将它们写出时,它们报告为不再需要读取字节。因此,在执行任何此类操作之前,您需要以某种方式重置其位置。
Buffer
提供了几种方法,其中最容易使用的是flip()
。正如您在文档here中所看到的,其用法如下:
翻转此缓冲区。将限制设置为当前位置,然后 该位置设置为零。如果标记已定义,则为 丢弃。
在执行一系列通道读取或放置操作之后,调用此方法 为一系列的通道写入或相对获取操作做准备
因此,在将它们写出之前,您需要翻转它们。另外,由于您正在尝试java.nio
,所以我不明白为什么不应该使用try with resources
语句来管理各种资源。这样,您将避免关闭过多的模板资源,因为这些资源可以手动自动关闭。
使用这些代码可以大大缩小代码的可读性:
public static void gather() {
ByteBuffer header = ByteBuffer.allocate(10);
ByteBuffer body = ByteBuffer.allocate(10);
byte[] b1 = { '0', '1' };
byte[] b2 = { '2', '3' };
header.put(b1);
body.put(b2);
//flip buffers before writing them out.
header.flip();
body.flip();
ByteBuffer[] buffs = { header, body };
try(FileOutputStream os = new FileOutputStream("d:/scattingAndGather.txt");
FileChannel channel = os.getChannel()) {
channel.write(buffs);
} catch (IOException e) {
e.printStackTrace();
}
}