我正在尝试将文件的一部分从一个文件通道复制到另一个文件通道(实际上,写入一个新文件等于第一个文件)。
所以,我正在读取 256kb 的块,然后将它们放回另一个通道
static void openfile(String str) throws FileNotFoundException, IOException {
int size=262144;
FileInputStream fis = new FileInputStream(str);
FileChannel fc = fis.getChannel();
byte[] barray = new byte[size];
ByteBuffer bb = ByteBuffer.wrap(barray);
FileOutputStream fos = new FileOutputStream(str+"2" /**/);
FileChannel fo = fos.getChannel();
StringBuilder sb;
while (fc.read(bb) != -1) {
fo.write(bb /**/);
bb.clear();
}
}
问题是 fo.write(我认为)从通道的开头再次写入,因此新文件仅由最后一个读取的块组成。
我尝试使用fo.write (bb, bb.position())
但它没有按预期工作(指针是否返回到通道的开头?),并且FileOutputStream(str+"2", true)
认为它会附加到新文件的末尾,但它没有。
我需要处理 256kb 的块,所以我不能改变程序的结构(除非我做了一些非常错误的事情)
已通过bb.flip();
解决
while (fi.read(bb) != -1) {
bb.flip();
fo.write(bb);
bb.clear();
}
这是一个非常古老的问题,但我偶然发现了它,尽管我可能会添加另一个答案,该答案使用FileChannel.transferTo或FileChannel.transferFrom可能会具有更好的性能。 根据javadoc:
此方法可能比从源通道读取并写入此通道的简单循环高效得多。许多操作系统可以直接将字节从源通道传输到文件系统缓存中,而无需实际复制它们。
public static void copy(FileChannel src, FileChannel dst) throws IOException {
long size = src.size();
long transferred = 0;
do {
transferred += src.transferTo(0, size, dst);
} while (transferred < size);
}
在大多数情况下,如果非通道不阻塞,则简单的src.transferTo(0, src.size(), dst);
将起作用。
在通道之间复制的规范方法如下:
while (in.read(bb) > 0 || bb.position() > 0)
{
bb.flip();
out.write(bb);
bb.compact();
}
您编辑的答案中的简化版本并非在所有情况下都有效,例如,当"out"是非阻塞时。