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

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).


I think you are looking for inputstream.available(). It does not tell you whether its empty but it can give you an indication as to whether data is there to be read or not.


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);
  }