为什么缓冲区没有被写入 FileChannel
why the buffers have not been write into the FileChannel
我正在学习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,这个例子有什么问题吗?
出现问题的原因是您从未重置缓冲区的位置。
当您创建两个 ByteBuffer
对象时,它们从位置零开始。每当您向其中添加内容时,它们的位置都会前进,这意味着当您尝试将它们写出时,它们会报告没有更多字节可供读取。因此,在进行任何此类操作之前,您需要以某种方式重置它们的位置。
Buffer
提供了一些方法,其中最容易使用的是 flip()
。正如您在文档here中看到的,它的用法如下:
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.
After a sequence of channel-read or put operations, invoke this method
to prepare for a sequence of channel-write or relative get operations
因此在写出它们之前你需要翻转它们。此外,由于您正在试验 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();
}
}
我正在学习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,这个例子有什么问题吗?
出现问题的原因是您从未重置缓冲区的位置。
当您创建两个 ByteBuffer
对象时,它们从位置零开始。每当您向其中添加内容时,它们的位置都会前进,这意味着当您尝试将它们写出时,它们会报告没有更多字节可供读取。因此,在进行任何此类操作之前,您需要以某种方式重置它们的位置。
Buffer
提供了一些方法,其中最容易使用的是 flip()
。正如您在文档here中看到的,它的用法如下:
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.
After a sequence of channel-read or put operations, invoke this method to prepare for a sequence of channel-write or relative get operations
因此在写出它们之前你需要翻转它们。此外,由于您正在试验 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();
}
}