yangxu998 / guava-libraries

Automatically exported from code.google.com/p/guava-libraries
Apache License 2.0
0 stars 0 forks source link

ByteBufferData{Input,Output}Stream #592

Closed GoogleCodeExporter closed 9 years ago

GoogleCodeExporter commented 9 years ago
NIO already provides a way to convert {Readable,Writable}ByteChannel instances 
to {Input,Output}Stream, respectively. It does not provide that sort of 
interface for a ByteBuffer, however.

The attached classes provide a way to view a ByteBuffer as an InputStream or 
OutputStream, including an implementation of the DataInput and DataOutput 
interfaces respectively (which make use of the ByteBuffer's own endianness 
setting). This makes it possible to link legacy code using any of these 
interfaces to a NIO ByteBuffer.

This becomes even more useful in the context of a MappedByteBuffer, which 
functions as a ByteBuffer rather than a Channel. Via the classes contributed 
here, it's possible for the same java.io-compatible code to work on "plain" 
streams or memory-mapped files regardless of backing implementation. To add to 
this capability, ByteBufferDataOutputStream.flush() will call 
MappedByteBuffer.force() if the buffer is mapped.

Technical note: The weird-looking convertException() bit exists to make these 
classes function more like the java.io equivalents. It catches the (unchecked) 
Buffer*Exception instances, and throws a checked EOFException instead. For 
simplicity, and to avoid synchronization overhead, NullPointerException -- 
which should only happen when the internal "buf" has been nulled out by close() 
-- is also caught and converted to a ClosedChannelException, a subclass of 
IOException.

Original issue reported on code.google.com by tv@duh.org on 5 Apr 2011 at 5:34

Attachments:

GoogleCodeExporter commented 9 years ago
Revision: added Preconditions.checkNotNull() at the top of all methods 
accepting a reference argument, so that those don't get converted to 
ClosedChannelException.

I did not add this to the ctors, as that's arguably a valid use case (the 
stream is closed already at constructor time). That check could be added if 
desired, though.

Original comment by tv@duh.org on 5 Apr 2011 at 5:39

Attachments:

GoogleCodeExporter commented 9 years ago
I don't know if the ByteBufferDataInputStream is the way we want to address the 
problem or not, but we do want to make sure that *something* is covering this 
use case properly.

Original comment by kevinb@google.com on 13 Jul 2011 at 7:43

GoogleCodeExporter commented 9 years ago

Original comment by cpov...@google.com on 13 Jul 2011 at 7:43

GoogleCodeExporter commented 9 years ago
It seemed to be the natural place to offer this conversion. Channels are 
already convertible to stream via the static methods in 
java.nio.channel.Channels, but there's no prefab way to convert a buffer (such 
as would be obtained when mmap'ing a file).

Nobody is required to use the DataInput/DataOutput interfaces; I added them as 
a logical-to-me extension, because a ByteBuffer already has notions of 
endianness and data conversion built-in. They function fine as bare 
{Input,Output}Stream instances too.

Original comment by tv@duh.org on 13 Jul 2011 at 7:50

GoogleCodeExporter commented 9 years ago

Original comment by fry@google.com on 10 Dec 2011 at 4:04

GoogleCodeExporter commented 9 years ago

Original comment by kevinb@google.com on 30 May 2012 at 7:43

GoogleCodeExporter commented 9 years ago
A few things about the implementation of the InputStream as given.

First, it is trivial to support the mark/reset/markSupported operations. Might 
as well throw them in.

Also, it might be nice to have the classes extend Buffered{Input,Output}Stream. 
Because they are in fact buffered.

There is an issue with those pesky superclass fields, though. If you don't mind 
extra ints/null references hanging around, then you can use this constructor:

    ByteBufferInputStream(ByteBuffer buffer) {
       super(null, 1);
       this.buf = buffer;
       super.buf = null;
    }

Original comment by michael....@gmail.com on 24 Dec 2012 at 11:48

GoogleCodeExporter commented 9 years ago
As for mark/reset, I actually have no idea why I didn't implement those. 
Probably an oversight. Yes, they can be implemented.

On subclassing: I chose Data{Input,Output}Stream as those classes are 
well-known to a lot of third party code, and are actually used in the method 
signatures of some methods. (Sure, in theory they should use generics, e.g. <? 
extends DataInput & Flushable & Closeable>, but that's still not commonplace. 
Plenty of code directly requests a Data*Stream.)

I've yet to see any code that actually cares about seeing a BufferedInputStream 
or BufferedOutputStream -- these seem only useful as add-in layers to implement 
buffering under the hood, not as a capability-marking class. I think it would 
be a bit of a mistake to extend those, since the superclass's buffering isn't 
going to be used anyway.

Original comment by tv@duh.org on 24 Dec 2012 at 9:17

GoogleCodeExporter commented 9 years ago
I'm not sold on the BufferedInputStream either, I was just implementing a 
ByteSource based on an array of ByteBuffers and had just coded up 
BufferInputStream when I noticed ByteSource has openBufferedStream(). I was 
just throwing the idea out there.

I think good use would check for markSupported() instead of instanceof 
BufferedInputStream; but then again, ByteSource doesn't.

Original comment by michael....@gmail.com on 24 Dec 2012 at 10:07

GoogleCodeExporter commented 9 years ago
I find it strange that these classes don't do more to manager the mark, e.g., I 
would have expected the byte buffer to be exactly as it was, mark and all, 
after closing the input stream

Original comment by pjul...@gmail.com on 2 Feb 2013 at 4:54

GoogleCodeExporter commented 9 years ago
This issue has been migrated to GitHub.

It can be found at https://github.com/google/guava/issues/<id>

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:15

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 1 Nov 2014 at 4:18

GoogleCodeExporter commented 9 years ago

Original comment by cgdecker@google.com on 3 Nov 2014 at 9:09