0

I want to transfer big file by file channel efficiently, so I use java.io.RandomAccessFile and java.nio.channels.FileChannel to transfer file.

And I get the output file is not right, which is less than the origin source file. Here is the code:

    public static void transferByRandomAccess(String inputFile, String outputFile) throws IOException {
        RandomAccessFile inputRandomAccessFile = null;
        RandomAccessFile outputRandomAccessFile = null;
        try {
            inputRandomAccessFile = new RandomAccessFile(inputFile, "r");
            FileChannel inputFileChannel = inputRandomAccessFile.getChannel();
            outputRandomAccessFile = new RandomAccessFile(outputFile, "rw");
            FileChannel outFileChannel = outputRandomAccessFile.getChannel();
            inputFileChannel.transferTo(0, inputFileChannel.size(), outFileChannel);
            inputFileChannel.force(true);
            outFileChannel.force(true);         
        } finally {
            if (outputRandomAccessFile != null) {
                outputRandomAccessFile.close();
            }
            if (inputRandomAccessFile != null) {
                inputRandomAccessFile.close();
            }
        }
    }

By the way, my input file is a mkv video file, whose size is 2937236651 byte. And while I copy it with java.io.BufferedInputStream and java.io.BufferedOutputStream, there is no problem.

Yanhui Zhou
  • 872
  • 6
  • 20
  • I've tried your code and it works well, what is the difference ? – VinhNT Mar 29 '16 at 02:57
  • @VinhNT no difference, I just copy the function, and paste here. – Yanhui Zhou Mar 29 '16 at 03:01
  • I tried with C:\file1.zip to C:\file2.zip, before application, there is no C:\file2.zip, after that, file2.zip has been created and has the same size (in Bytes) with file1.zip – VinhNT Mar 29 '16 at 03:03

2 Answers2

1

Well, for your new update, the file is larger than 2GB, there is a limit of OS to make buffer for such operation, in this case you need to update your application to make it works for file larger than 2GB

public class Test {

    public static void main(String[] args) throws Exception {
        RandomAccessFile inputRandomAccessFile = null;
        RandomAccessFile outputRandomAccessFile = null;
        try {
            inputRandomAccessFile = new RandomAccessFile("G:\\file1.zip", "r");
            FileChannel inputFileChannel = inputRandomAccessFile.getChannel();
            outputRandomAccessFile = new RandomAccessFile("G:\\file2.zip", "rw");
            FileChannel outFileChannel = outputRandomAccessFile.getChannel();
            long readFileSize = inputFileChannel.size();
            long transferredSize = 0;
            do {
                long count = inputFileChannel.transferTo(transferredSize, inputFileChannel.size(), outFileChannel);
                transferredSize += count;
            } while (transferredSize < readFileSize);

            inputFileChannel.force(true);
            outFileChannel.force(true);
        } finally {
            if (outputRandomAccessFile != null) {
                outputRandomAccessFile.close();
            }
            if (inputRandomAccessFile != null) {
                inputRandomAccessFile.close();
            }
        }
        System.out.println("DONE");
    }
}
VinhNT
  • 1,091
  • 8
  • 13
1

Your copy step is wrong. transferTo() isn't specified to transfer the entire input in one call. That's why it returns a count. You have to loop, advancing the offset and decrementing the length until there is nothing left to transfer.

user207421
  • 305,947
  • 44
  • 307
  • 483