web-dev-qa-db-fra.com

Comment puis-je vérifier si un InputStream est vide sans y lire?

Je veux savoir si un InputStream est vide, mais sans utiliser la méthode read(). Existe-t-il un moyen de savoir s'il est vide sans en lire?

52
Jenny Smith

Je pense que vous recherchez inputstream.available() . Il ne vous dit pas s'il est vide mais il peut vous indiquer si des données doivent être lues ou non.

37
vpram86

Non, tu ne peux pas. InputStream est conçu pour fonctionner avec des ressources distantes, vous ne pouvez donc pas savoir s'il est là tant que vous ne l'avez pas lu.

Vous pourrez peut-être utiliser un Java.io.PushbackInputStream, cependant, ce qui vous permet de lire à partir du flux pour voir s'il y a quelque chose, puis de le "repousser" vers le haut du flux (ce n'est pas ainsi que cela fonctionne vraiment, mais c'est ainsi qu'il se comporte avec le code client).

56
skaffman

Basé sur la suggestion d'utiliser le PushbackInputStream, vous trouverez un exemple d'implémentation ici:

/**
 * @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);
    }
  }

}

Et voici quelques tests réussis:

  @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);
  }
9
Sebastien Lorber

Vous pouvez utiliser la méthode available() pour demander au flux s'il existe des données disponibles au moment où vous l'appelez . Cependant, cette fonction n'est pas garantie de fonctionner sur tous les types de flux d'entrée. Cela signifie que vous ne pouvez pas utiliser available() pour déterminer si un appel à read() va réellement bloquer ou non.

4
Greg Hewgill

Si le InputStream que vous utilisez prend en charge la prise en charge de la marque/réinitialisation, vous pouvez également essayer de lire le premier octet du flux, puis le réinitialiser à sa position d'origine:

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

Si vous ne contrôlez pas le type de InputStream que vous utilisez, vous pouvez utiliser la méthode markSupported() pour vérifier si la marque/réinitialisation fonctionnera sur le flux et revenir à available() ou sinon la méthode Java.io.PushbackInputStream.

4
Henning

Que diriez-vous d'utiliser inputStreamReader.ready () pour le savoir?

import Java.io.InputStreamReader;

/// ...

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

// ...
1
shaolang