![JAR search and dependency download from the Maven repository](/logo.png)
net.sf.kdgcommons.io.ChannelInputStream Maven / Gradle / Ivy
Show all versions of kdgcommons Show documentation
// Copyright Keith D Gregory
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
package net.sf.kdgcommons.io;
import java.io.IOException;
import java.io.InputStream;
import java.nio.ByteBuffer;
import java.nio.channels.ReadableByteChannel;
/**
* A decorator that provides InputStream
operations backed by a
* java.nio.Channel
. This allows programs to use the flexibility
* of the channel API (such as random seeks on FileChannel
)
* while still using the java.io
class hierarchy (in particular,
* InputStreamReader
).
*
* This class does not attempt to replicate channel functionality. The program
* should maintain an independent reference to the channel to support operations
* such as position()
. See method docs for cases where stream
* functionality overlaps channel functionality.
*
* Single instances of this class are not safe for concurrent use by multiple
* threads. Multiple instances that share a channel are thread-safe if the
* channel is thread-safe.
*/
public class ChannelInputStream
extends InputStream
{
private ReadableByteChannel _channel;
// for single-byte reads we'll reuse the buffer rather than recreate
// (premature optimization, maybe, but why allocate objects we don't need?)
private byte[] _singleByte = new byte[1];
private ByteBuffer _singleByteBuf = ByteBuffer.wrap(_singleByte);
public ChannelInputStream(ReadableByteChannel channel)
{
_channel = channel;
}
//----------------------------------------------------------------------------
// InputStream
//----------------------------------------------------------------------------
/**
* Always returns false
. If the underlying channel supports
* marks and positioning, you should perform those operations there.
*/
@Override
public boolean markSupported()
{
return false;
}
/**
* Reads a single byte from the channel. Returns the byte's value, or -1 to
* indicate either end-of-file or no bytes available on channel.
*
* Unlike the InputStream
implementations in java.io
,
* end-of-file is "soft": some channels will increase their size. As a result,
* you can call this method after receiving end-of-file notification and get
* valid data.
*/
@Override
public int read()
throws IOException
{
_singleByteBuf.clear();
int flag = _channel.read(_singleByteBuf);
if (flag <= 0)
return -1;
return _singleByte[0] & 0xFF;
}
/**
* Attempts to fill the passed array from the channel, returning the number of
* bytes read (which may be 0), or -1 to indicate end-of-file.
*
* Unlike the InputStream
implementations in java.io
,
* end-of-file is "soft": some channels will increase their size. As a result,
* you can call this method after receiving end-of-file notification and get
* valid data.
*/
@Override
public int read(byte[] b) throws IOException
{
return read(b, 0, b.length);
}
/**
* Attempts to fill a section of the passed array from the channel, returning
* the number of bytes read (which may be 0), or -1 to indicate end-of-file.
*
* Unlike the InputStream
implementations in java.io
,
* end-of-file is "soft": some channels will increase their size. As a result,
* you can call this method after receiving end-of-file notification and get
* valid data.
*/
@Override
public int read(byte[] b, int off, int len) throws IOException
{
ByteBuffer buf = ByteBuffer.wrap(b, off, len);
return _channel.read(buf);
}
/**
* Closes this stream, along with the underlying channel.
*/
@Override
public void close() throws IOException
{
_channel.close();
}
/**
* This method always returns 0; there is no way to discover the number of
* available bytes from a generic channel.
*/
@Override
public int available() throws IOException
{
return 0;
}
/**
* Attempts to skip the specified number of bytes from the channel.
*
* Per InputStream
, this is a best-effort method. You should either
* use {@link IOUtil#skipFully} or position the channel explicitly.
*/
@Override
public long skip(long n) throws IOException
{
return super.skip(n);
}
}