java read / write construction
Asked Answered
E

3

6

Can someone explain me why this construction wont work:

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

and this one works just fine:

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

As for me they are identical, but 1st one wont write data correctly (will write half of file lenght / data).

Euphonize answered 6/10, 2015 at 12:49 Comment(4)
Is there a loop you aren't showing us? Because read() only reads a segment of data. Generally speaking that segment is determined by a container an int is 32 bits where as fileoutputstream takes varible amounts of bytesThrove
They are the same. Note that this does not copy the entire content of the input stream to the output stream. It will read and write just one byte.Gearing
if you wanted to make it work you should input a byte buffer docs.oracle.com/javase/7/docs/api/java/io/…Throve
Don't use fileInputStream.available() for a loop read. It doesn't do what you think it does. It just tells you how many bytes are available without blocking - which is not necessarily the length of the file. This could affect your results regaldless of the variable issue.Roadability
F
9

You are using the available() method incorrectly. The method is used to determine how many bytes are available to be read without blocking the thread.

Good Stack Overflow Question about available()

JavaDoc on available()


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

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

This method is probably going to be quite slow if you try to read in larger amounts of data. You can speed this up by reading in more bytes using the read(byte[] b, int off, int len) method. The loop will look quite similar to the other one.

byte [] buffer = new byte[1024]; // 1kb buffer
int numBytesRead = fileInputStream.read(buffer);
while (numBytesRead != -1) {
    fileOutputStream.write(buffer, 0, numBytesRead);
    numBytesRead = fileInputStream.read(buffer);
}
Flaxseed answered 6/10, 2015 at 13:9 Comment(0)
H
1

My interest of 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 a single byte from /home/nick/foo and wrote it to /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();
}

Copied the entire file. (note - I would not recommend copying a file a byte at a time, use the Buffered I/O classes to copy whole chunks)

Did you by any chance forget to flush() and close() to OutputStream?

Horning answered 6/10, 2015 at 13:0 Comment(4)
I updated first post - thougt loop wont matter in this question. There is loop and there is differenceEuphonize
I checked it: yes it copies file and some data can be read from it, but contents is definetely damaged.Euphonize
I closed it but not flushed. It works with flush(). Can you expain why? According to javadoc "The flush method of OutputStream does nothing."Euphonize
" Can you explain why?" : honest answer: no.Horning
D
1

Seems like your while loop is doing estimated things and skipping here and there.

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

Returns an estimate of the number of remaining bytes that can be read (or skipped over) from this input stream without blocking by the next invocation of a method for this input stream. The next invocation might be the same thread or another thread. A single read or skip of this many bytes will not block, but may read or skip fewer bytes. In some cases, a non-blocking read (or skip) may appear to be blocked when it is merely slow, for example when reading large files over slow networks.

See here

Dispirited answered 6/10, 2015 at 13:7 Comment(1)
Thank you, seems to me it is what happens here.Euphonize

© 2022 - 2024 — McMap. All rights reserved.