Question

Was writing the javadoc for :

/**
 * ...Buffers the input stream so do not pass in a BufferedInputStream ...
 */
public static void meth(InputStream is) throws IOException {
    BufferedInputStream bis = new BufferedInputStream(is,
            INPUT_STREAM_BUFFER_SIZE);
    // rest omitted
}

But is it really a problem to pass a buffered input stream in ? So this :

InputStream is = new BufferedInputStream(new FileInputStream("C:/file"), SIZE);
meth(is);

would buffer the is into bis - or would java detect that is is already buffered and set bis = is ? If yes, would different buffer sizes make a difference ? If no, why not ?
NB : I am talking about input streams but actually the question is valid for output streams too

Was it helpful?

Solution

But is it really a problem to pass a buffered input stream in ?

Not really. There is potentially a small overhead in doing this, but it is negligible compared with the overall cost of reading input.

If you look at the code of BufferedInputStream, (e.g. the read1 method) you will see that block reads are implemented to be efficient when buffered streams are stacked.

[Re the example code:] would java detect that is is already buffered and set bis = is ?

No.

If no, why not ?

Because Java (the language, the compiler) generally doesn't understand the semantics of Java library classes. And in this case, since the benefit of such an optimization would be negligible, it i not worthwhile implementing.

Of course, you are free to write your meth method to do this kind of thing explicitly ... though I predict that it will make little difference.


I do not quite get why in read1 they "bother" to copy to the input buffer only if the requested length is less than the buf.length (or if there is a marked position in the input stream)

I assume that you are referring to this code (in read1):

    if (len >= getBufIfOpen().length && markpos < 0) {
        return getInIfOpen().read(b, off, len);
    }

The first part is saying that if the user is asking for less than the stream's configured buffer size, we don't want to short-circuit the buffering. (Otherwise, we'd have the problem that doing a read(byte[], int, int) with a small requested length would be pessimal.)

The second part is to do with the way that mark / reset is implemented. Instead of using mark / reset on the underlying stream (which may or may not be supported), a BufferedInputStream uses the buffer to implement it. What you are seeing is part of that logic. (You can work the details for yourself ... reading the comments in the source code.)

OTHER TIPS

If you buffer the stream twice then it will use more memory and be slower than if you only did so once, but it will still work.

It's certainly worth documenting that your stream does buffering so that users will know they don't need to do so themselves.

Generally it's best to discourage rather than actively prevent this sort of misuse.

The answer is no, Java would not detect the double buffering.

It is up to the user to avoid this problem. The BufferedInputStream has no way of knowing whether the InputStream you pass into the constructor is buffered or not.

Here is the source code for the BufferedInputStream constructor:

public BufferedInputStream(InputStream in, int size) {
    super(in);
    if (size <= 0) {
        throw new IllegalArgumentException("Buffer size <= 0");
    }
    buf = new byte[size];
}

EDIT

From the comments is it a problem to double buffer a stream?

The short answer is yes.

The idea of buffering is to increase speed so that data is spooled into memory and written out (usually to very slow IO) in chunks. If you double buffer you spool data into memory and then flush that data back into memory somewhere else. This certainly has a cost in terms of speed...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top