【问题标题】:Copy from a filechannel to another从一个文件通道复制到另一个
【发布时间】:2013-10-21 08:40:43
【问题描述】:

我正在尝试将文件的一部分从文件通道复制到另一个(写入一个新文件,实际上等于第一个文件)。

所以,我正在读取 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();
    }

【问题讨论】:

标签: java io stream


【解决方案1】:

频道间复制的规范方式如下:

while (in.read(bb) > 0 || bb.position() > 0)
{
    bb.flip();
    out.write(bb);
    bb.compact();
}

您编辑的答案中的简化版本并非在所有情况下都有效,例如当 'out' 是非阻塞时。

【讨论】:

  • 非阻塞是什么意思?
  • 查一下。一些频道,例如SocketChannels, 可以进入非阻塞模式,这意味着write() 可以在没有写入所有数据或任何数据的情况下返回。这使得compact() 必不可少,而不是clear(),并使position() > 0 的额外测试在流结束时也必不可少。
【解决方案2】:

这是一个非常古老的问题,但我偶然发现了它,尽管我可能会添加另一个使用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); 将起作用。

【讨论】:

    猜你喜欢
    • 2016-10-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-01-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-17
    相关资源
    最近更新 更多