[java] How can I check if an InputStream is empty without reading from it?

I want to know if an InputStream is empty, but without using the method read(). Is there a way to know if it's empty without reading from it?

This question is related to java inputstream

The answer is


Without reading you can't do this. But you can use a work around like below.

You can use mark() and reset() methods to do this.

mark(int readlimit) method marks the current position in this input stream.

reset() method repositions this stream to the position at the time the mark method was last called on this input stream.

Before you can use the mark and reset, you need to test out whether these operations are supported on the inputstream you’re reading off. You can do that with markSupported.

The mark method accepts an limit (integer), which denotes the maximum number of bytes that are to be read ahead. If you read more than this limit, you cannot return to this mark.

To apply this functionalities for this use case, we need to mark the position as 0 and then read the input stream. There after we need to reset the input stream and the input stream will be reverted to the original one.

    if (inputStream.markSupported()) {
          inputStream.mark(0);
          if (inputStream.read() != -1) {
               inputStream.reset();
          } else {
               //Inputstream is empty
          }
    }

Here if the input stream is empty then read() method will return -1.


If the InputStream you're using supports mark/reset support, you could also attempt to read the first byte of the stream and then reset it to its original position:

input.mark(1);
final int bytesRead = input.read(new byte[1]);
input.reset();
if (bytesRead != -1) {
    //stream not empty
} else {
    //stream empty
} 

If you don't control what kind of InputStream you're using, you can use the markSupported() method to check whether mark/reset will work on the stream, and fall back to the available() method or the java.io.PushbackInputStream method otherwise.


You can use the available() method to ask the stream whether there is any data available at the moment you call it. However, that function isn't guaranteed to work on all types of input streams. That means that you can't use available() to determine whether a call to read() will actually block or not.


public void run() {
    byte[] buffer = new byte[256];  
    int bytes;                      

    while (true) {
        try {
            bytes = mmInStream.read(buffer);
            mHandler.obtainMessage(RECIEVE_MESSAGE, bytes, -1, buffer).sendToTarget();
        } catch (IOException e) {
            break;
        }
    }
}

Based on the suggestion of using the PushbackInputStream, you'll find an exemple implementation here:

/**
 * @author Lorber Sebastien <i>([email protected])</i>
 */
public class NonEmptyInputStream extends FilterInputStream {

  /**
   * Once this stream has been created, do not consume the original InputStream 
   * because there will be one missing byte...
   * @param originalInputStream
   * @throws IOException
   * @throws EmptyInputStreamException
   */
  public NonEmptyInputStream(InputStream originalInputStream) throws IOException, EmptyInputStreamException {
    super( checkStreamIsNotEmpty(originalInputStream) );
  }


  /**
   * Permits to check the InputStream is empty or not
   * Please note that only the returned InputStream must be consummed.
   *
   * see:
   * http://stackoverflow.com/questions/1524299/how-can-i-check-if-an-inputstream-is-empty-without-reading-from-it
   *
   * @param inputStream
   * @return
   */
  private static InputStream checkStreamIsNotEmpty(InputStream inputStream) throws IOException, EmptyInputStreamException {
    Preconditions.checkArgument(inputStream != null,"The InputStream is mandatory");
    PushbackInputStream pushbackInputStream = new PushbackInputStream(inputStream);
    int b;
    b = pushbackInputStream.read();
    if ( b == -1 ) {
      throw new EmptyInputStreamException("No byte can be read from stream " + inputStream);
    }
    pushbackInputStream.unread(b);
    return pushbackInputStream;
  }

  public static class EmptyInputStreamException extends RuntimeException {
    public EmptyInputStreamException(String message) {
      super(message);
    }
  }

}

And here are some passing tests:

  @Test(expected = EmptyInputStreamException.class)
  public void test_check_empty_input_stream_raises_exception_for_empty_stream() throws IOException {
    InputStream emptyStream = new ByteArrayInputStream(new byte[0]);
    new NonEmptyInputStream(emptyStream);
  }

  @Test
  public void test_check_empty_input_stream_ok_for_non_empty_stream_and_returned_stream_can_be_consummed_fully() throws IOException {
    String streamContent = "HELLooooô wörld";
    InputStream inputStream = IOUtils.toInputStream(streamContent, StandardCharsets.UTF_8);
    inputStream = new NonEmptyInputStream(inputStream);
    assertThat(IOUtils.toString(inputStream,StandardCharsets.UTF_8)).isEqualTo(streamContent);
  }

How about using inputStreamReader.ready() to find out?

import java.io.InputStreamReader;

/// ...

InputStreamReader reader = new InputStreamReader(inputStream);
if (reader.ready()) {
    // do something
}

// ...

No, you can't. InputStream is designed to work with remote resources, so you can't know if it's there until you actually read from it.

You may be able to use a java.io.PushbackInputStream, however, which allows you to read from the stream to see if there's something there, and then "push it back" up the stream (that's not how it really works, but that's the way it behaves to client code).