3

I would like to use bufferedInputStream and bufferedOutputStream to copy large binary files from source file to destination file.

Here is my code:

   byte[] buffer = new byte[1000];        
    try {
        FileInputStream fis = new FileInputStream(args[0]);
        BufferedInputStream bis = new BufferedInputStream(fis);

        FileOutputStream fos = new FileOutputStream(args[1]);
        BufferedOutputStream bos = new BufferedOutputStream(fos);

        int numBytes;
        while ((numBytes = bis.read(buffer))!= -1)
        {
            bos.write(buffer);
        }
        //bos.flush();
        //bos.write("\u001a");

        System.out.println(args[0]+ " is successfully copied to "+args[1]);

        bis.close();
        bos.close();
    } catch (IOException e)
    {
        e.printStackTrace();
    }

I can successfully copy but then I use

cmp src dest

in the command line to compare two files. The error message

cmp: EOF on files

appears. May I know where I was wrong?

Santhosh
  • 8,045
  • 2
  • 26
  • 54

4 Answers4

9

This is the mistake:

bos.write(buffer);

You're writing out the whole buffer, even if you only read data into part of it. You should use:

bos.write(buffer, 0, numBytes);

I'd also suggest using try-with-resources if you're using Java 7 or later, or put the close calls in a finally block otherwise.

As Steffen notes, Files.copy is a simpler approach if that's available to you.

Jon Skeet
  • 1,261,211
  • 792
  • 8,724
  • 8,929
2

If you are using Java 8 try the Files.copy(Path source, Path target) method.

Steffen
  • 352
  • 1
  • 12
  • some additional information about copying files: http://www.journaldev.com/861/4-ways-to-copy-file-in-java – Steffen Jan 23 '15 at 10:25
2

you need to close your FileOutputStream and FileInputStream

Also you can use FileChannel to copy like as follows

FileChannel from = new FileInputStream(sourceFile).getChannel();
FileChanngel to = new FileOutputStream(destFile).getChannel();
to.transferFrom(from, 0, from.size());
from.close();
to.close();
shikjohari
  • 2,147
  • 8
  • 23
  • That's copying a byte at a time though - very inefficient. – Jon Skeet Jan 23 '15 at 10:29
  • Yep, copy one byte per time is too inefficient. –  Jan 23 '15 at 10:32
  • @JonSkeet yep modified, – shikjohari Jan 23 '15 at 10:38
  • I found that this didn't work when copying files larger (100GB) than the remaining free space on my C: drive (where the app is running). I am currently trying to use `BufferedInputStream` and `BufferedOutputStream` which appears to be working, but kinda slow. Is there an even faster version of this answer that doesn't require space free on the C: drive? Perhaps some version of the buffered streams? – trademark Nov 05 '20 at 18:25
0

You could use IOUtils from apatch-commons library

I think copyLarge fucntion it that you need

Akvel
  • 829
  • 1
  • 13
  • 29
  • as stated in this article (http://www.journaldev.com/861/4-ways-to-copy-file-in-java), the apache-commons is the slowest solution. – Steffen Jan 23 '15 at 10:36