Java read / write construct

Can someone explain to me why this construct does not work:

while (fileInputStream.available()>0) { fileOutputStream.write(fileInputStream.read()); } 

and this works fine:

 while (fileInputStream.available()>0) { int data = fileInputStream.read(); fileOutputStream.write(data); } 

As for me they are identical, but the 1st one will not write data correctly (it will write half the length of the file / data).

+6
source share
3 answers

You are using the available() method incorrectly. This method is used to determine the number of bytes available for reading without blocking the stream.

Good stack overflow question about available ()

JavaDoc for available ()


The correct way to check if you have reached EOF is to check if read() method -1 returned:

 int data = fileInputStream.read(); while (data != -1) { fileOutputStream.write(data); data = fileInputStream.read(); } 

This method is likely to be rather slow if you try to read in large amounts of data. You can speed this up by reading more bytes with the read(byte[] b, int off, int len) method read(byte[] b, int off, int len) . The cycle will be similar to another.

 byte [] buffer = new byte[1024]; // 1kb buffer int numBytesRead = fileInputStream.read(buffer); while (numBytesRead != -1) { fileOutputStream.write(buffer, 0, numBytesRead); numBytesRead = fileInputStream.read(buffer); } 
+9
source

My interest in piqued I wrote this little test:

 public static void main(String[] args) throws IOException { FileInputStream fileInputStream = new FileInputStream("/home/nick/foo"); FileOutputStream fileOutputStream = new FileOutputStream("/home/nick/bar"); fileOutputStream.write(fileInputStream.read()); fileOutputStream.flush(); fileOutputStream.close(); fileInputStream.close(); } 

It worked as expected - read one byte from /home/nick/foo and wrote it in /home/nick/bar

EDIT:

Updated program:

 public static void main(String[] args) throws IOException { FileInputStream fileInputStream = new FileInputStream("/home/nick/foo"); FileOutputStream fileOutputStream = new FileOutputStream("/home/nick/bar"); while (fileInputStream.available()>0) { fileOutputStream.write(fileInputStream.read()); } fileOutputStream.flush(); fileOutputStream.close(); fileInputStream.close(); } 

I copied the entire file. (note - I would not recommend copying a file byte at a time, use buffered I / O classes to copy entire fragments)

Have you accidentally forgotten flush() and close() for OutputStream?

+1
source

Your while loop seems to be doing evaluative things and skipping here and there.

 public int available() throws IOException { return 0; } 

Returns an estimate of the number of bytes remaining that can be read (or skipped) from this input stream without blocking the next method call for this input stream. The next call may be the same thread or another thread. One reading or skipping this many bytes will not block, but can read or skip fewer bytes. In some cases, non-blocking reading (or skipping) can be blocked when it is just slow, for example, when reading large files on slow networks.

See here

+1
source

All Articles