Amac
Amac

Reputation: 57

Reading from an InputStream and writing to an OutputStream

This should be very simple, and I've searched Google, but didn't see anyone mentioning the issue I've noticed. Everything that I've seen does the same basic thing. Like this:

byte [] buffer = new byte[256];
int bytesRead = 0;
while((bytesRead = input.read(buffer)) != -1)
{
    output.write(buffer, 0, bytesRead);
}

I know read() returns -1 when EOF is reached, but what if the file is smaller than the buffer or even the same size? Fox example, a 200 byte file is being read in. I assume it read the 200 bytes, but returns -1. That matches the javadocs, but it also means the write() is never called. I would have expected to actually tell me it read the 200 bytes, and on the next iteration to return -1.

How can I get around this "issue"?

Upvotes: 3

Views: 28015

Answers (5)

Louis Wasserman
Louis Wasserman

Reputation: 198571

FYI, Guava has ByteStreams.copy(InputStream, OutputStream), which you can either use directly, or look at how it solves this problem.

Upvotes: 12

user207421
user207421

Reputation: 311052

I assume it read the 200 bytes, but returns -1

No. It reads the 200 bytes and returns 200. This is perfectly clear from the Javadoc, and you could also have tried it easily enough.

Upvotes: 0

msi
msi

Reputation: 2639

Your code

byte [] buffer = new byte[256];
int bytesRead = 0;
while((bytesRead = input.read(buffer)) != -1) {
    output.write(buffer, 0, bytesRead);
}

works OK.

For example imagine you have a file with 300 chars (600 bytes):

Step 1. buffer will read 256 bytes and rewrites them to output; 344 left to EOF

Step 2. buffer will read 256 bytes and rewrites them to output; 88 left to EOF

Step 3. buffer will read 88 bytes (byteRead == 88) and rewrites them to output; EOF left

Step 4. EOF (input.read(buffer) returns -1)

... edit

Above steps are not theory. I get this by rewriting actual file content with this code:

static void rewrite() throws IOException {
    InputStream input = new FileInputStream("file1.txt");
    OutputStream output = new FileOutputStream("file2.txt");
    byte[] buffer = new byte[256];
    int bytesRead = 0;
    while ((bytesRead = input.read(buffer)) != -1) {
        System.out.println(bytesRead);
        output.write(buffer, 0, bytesRead);
    }
}

maybe something else is wrong with your configuration.

Upvotes: 7

erickson
erickson

Reputation: 269897

At least two calls to read() would be required to detect the end of a non-empty stream. One to read the content, then another to return EOF.

As an example, if the buffer were 256 bytes, and the file only 200 bytes, a call to read(byte[]) would return 200 (or a sequence of call results would sum to 200), then subsequent calls would return -1 to signal EOF.

It's not totally clear how you've interpreted the Javadoc for InputStream, but it says clearly that it returns the number of bytes read, and returns -1 only when there were no more data to be read.

If the length of b is zero, then no bytes are read and 0 is returned; otherwise, there is an attempt to read at least one byte. If no byte is available because the stream is at the end of the file, the value -1 is returned; otherwise, at least one byte is read and stored into b.

Further:

Returns: The total number of bytes read into the buffer, or -1 [if] there [are] no more data because the end of the stream has been reached.

Upvotes: 1

mcdeck
mcdeck

Reputation: 126

read() returns the number of bytes read until the complete file has been read. It only returns -1 once no more bytes can be read.

From the java documentation (1.4)

If no byte is available because the stream is at end of file, the value -1 is returned; otherwise, at least one byte is read and stored into b.

It actually does what you want it to do. It reads the 200 bytes (or whatever is left in the file and is smaller than the buffer you supplied) and returns -1 on the next iteration.

Upvotes: 0

Related Questions