5

Is it possible to create non blocking ReadableByteChannel from InputStream object?

Channel.newChannel(inputStream) - produces channel which could be blocked by blocked InputStream.read invocation

Mikhail Tsaplin
  • 642
  • 1
  • 9
  • 21

3 Answers3

2

No it is not possible. See the Javadoc.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • But maybe some libraries exists? – Mikhail Tsaplin Oct 07 '14 at 07:59
  • No, it is not possible, see the Javadoc. No library can make impossible things possible. – user207421 Oct 17 '14 at 22:33
  • @downvoter Don't kid yourself. If you seriously believe the contrary, please post an answer of your own showing how, for comment, voting, etc. – user207421 Nov 08 '17 at 07:28
  • 2
    It is possible, just not advisable. It could be done at the expense of a `Thread` to pipe the blocking input to a non-blocking channel, but obviously that would defeat the motivating purpose of non-blocking io (i.e avoiding threads). – teppic Nov 10 '17 at 02:19
1

You may try to implement such a channel yourself, using 'Inputstream.avalable()' to avoid blocking. However, this method does not guarantee to return correct value, so you have to check the Inputstream implementation you use.

Are you sure you need non-blocking channel? Generally, it requires periodical polling to check arrival of data. Asynchronous channels, which invoke callbacks on data arrival, have more sense.

Alexei Kaigorodov
  • 13,189
  • 1
  • 21
  • 38
0

The ReadableByteChannel.newChannel method

public static ReadableByteChannel newChannel(final InputStream in) {
    checkNotNull(in, "in");

    if (in instanceof FileInputStream &&
        FileInputStream.class.equals(in.getClass())) {
        return ((FileInputStream)in).getChannel();
    }

    return new ReadableByteChannelImpl(in);
}

and the read method of ReadableByteChannelImpl

public int read(ByteBuffer dst) throws IOException {
    int len = dst.remaining();
    int totalRead = 0;
    int bytesRead = 0;
    synchronized (readLock) {
        while (totalRead < len) {
            int bytesToRead = Math.min((len - totalRead),
                                       TRANSFER_SIZE);
            if (buf.length < bytesToRead)
                buf = new byte[bytesToRead];
            if ((totalRead > 0) && !(in.available() > 0))
                break; // block at most once
            try {
                begin();
                bytesRead = in.read(buf, 0, bytesToRead);
            } finally {
                end(bytesRead > 0);
            }
            if (bytesRead < 0)
                break;
            else
                totalRead += bytesRead;
            dst.put(buf, 0, bytesRead);
        }
        if ((bytesRead < 0) && (totalRead == 0))
            return -1;

        return totalRead;
    }
}

so, it's just calling the read method of the InputStream, and the javadoc of the Inputstream's read method:

This method blocks until input data is available, end of file is detected, or an exception is thrown.

so you can implements a subclass of InputStream and override the read methods, and implement the methods as nonblocking.

Y.L.
  • 1,274
  • 6
  • 23
  • 39