从文件通道复制到另一个

时间:2013-10-13 19:07:33

标签: java io stream

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

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

2 个答案:

答案 0 :(得分:0)

在渠道之间复制的规范方法如下:

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

您编辑的答案中的简化版本并不适用于所有情况,例如:当'out'是非阻塞时。

答案 1 :(得分:0)

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