如何在不读取的情况下检查InputStream是否为空?

Jen*_*ith 53 java inputstream

我想知道a是否InputStream为空,但不使用该方法read().有没有办法知道它是否是空的而没有从中读取?

ska*_*man 59

不,你不能.InputStream设计用于远程资源,因此在您实际读取它之前,您无法知道它是否存在.

java.io.PushbackInputStream然而,您可以使用a ,它允许您从流中读取以查看是否存在某些内容,然后将其"向后推"到流中(这不是它真正起作用的方式,但这就是它的行为方式客户代码).

  • 如果你不知道你正在处理什么类型的流(即你有一个以InputStream作为参数的方法),PushbackInputStream似乎是最强大的解决方案. (5认同)

vpr*_*m86 37

我想你在找inputstream.available().它不会告诉您它是否为空,但它可以指示数据是否可以读取.

  • `available()`告诉你是否有数据准备好被读取,它不一定告诉你流是否为空. (28认同)
  • “没有完全做我所需要的”您实际上需要什么?是在加载缓冲区之前分配缓冲区,还是...? (2认同)
  • 为答案点赞。boo java 用于命名,看起来应该是布尔值,而不是 int。 (2认同)

Seb*_*ber 9

基于使用PushbackInputStream的建议,您将在此处找到一个示例实现:

/**
 * @author Lorber Sebastien <i>(lorber.sebastien@gmail.com)</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);
    }
  }

}
Run Code Online (Sandbox Code Playgroud)

以下是一些通过测试:

  @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);
  }
Run Code Online (Sandbox Code Playgroud)


Gre*_*ill 5

您可以使用该available()方法询问流在您调用它的那一刻是否有任何数据可用。但是,不能保证该函数适用于所有类型的输入流。这意味着您不能使用available()来确定调用是否read()会实际阻塞。

  • InputStream本身的available()方法默认返回0;如果子类不覆盖此方法,则将始终返回 0。 (5认同)

Hen*_*ing 5

如果InputStream您使用的是支持标记/重置支持,则还可以尝试读取流的第一个字节,然后将其重置为其原始位置:

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

如果您无法控制使用的是哪种类型InputStream,则可以使用该markSupported()方法来检查标记/重置是否可以在流上使用,然后退回到该available()方法或其他java.io.PushbackInputStream方法。