Question

Devrait être assez simple: j'ai un InputStream dans lequel je veux jeter un coup d'œil (et non pas lire) les deux premiers octets, c'est-à-dire que je veux la "position actuelle". du InputStream à rester à 0 après mon coup d’oeil. Quel est le moyen le plus sûr et le plus sûr de procéder?

Réponse : comme je l'avais soupçonné, la solution consistait à l'envelopper dans un flux BufferedInputStream offrant une possibilité de marquage. Merci Rasmus.

Était-ce utile?

La solution

Pour un InputStream général, je l'envelopperais dans un BufferedInputStream et ferais quelque chose comme ceci:

BufferedInputStream bis = new BufferedInputStream(inputStream);
bis.mark(2);
int byte1 = bis.read();
int byte2 = bis.read();
bis.reset();
// note: you must continue using the BufferedInputStream instead of the inputStream

Autres conseils

Lorsque vous utilisez un BufferedInputStream, assurez-vous que le inputStream n’est pas déjà mis en mémoire tampon; une double mise en mémoire tampon rendra très difficile la recherche de bogues. De plus, vous devez gérer les lecteurs différemment. La conversion en StreamReader et la mise en mémoire tampon entraînent la perte d'octets si le lecteur est mis en mémoire tampon. De même, si vous utilisez un lecteur, rappelez-vous que vous ne lisez pas des octets, mais des caractères dans le codage par défaut (sauf si un codage explicite a été défini). Un exemple de flux d'entrée mis en mémoire tampon, que vous ignorez peut-être, est l'URL de l'URL; url.openStream ();

Je n'ai aucune référence pour cette information, elle provient du code de débogage. Le principal cas où le problème s'est produit pour moi était un code qui lisait un fichier dans un flux compressé. Si je me souviens bien, une fois que vous avez commencé à déboguer à travers le code, il existe des commentaires dans le code source Java indiquant que certaines choses ne fonctionnent pas toujours correctement. Je ne me souviens pas d'où proviennent les informations provenant de BufferedReader et BufferedInputStream  vient de mais je pense que cela échoue tout de suite même sur le test le plus simple. Rappelez-vous que pour vérifier que vous devez marquer plus que la taille de la mémoire tampon (ce qui diffère de BufferedReader par rapport à BufferedInputStream), les problèmes surviennent lorsque les octets lus atteignent la fin de la mémoire tampon. Notez qu'il existe une taille de tampon de code source qui peut être différente de la taille de tampon que vous avez définie dans le constructeur. Cela fait longtemps que je n’ai pas fait cela, alors mes souvenirs des détails peuvent être un peu décalés. Les tests ont été effectués à l'aide de FilterReader / FilterInputStream, ajoutez-en un au flux direct et un au flux en mémoire tampon pour voir la différence.

J'ai trouvé l'implémentation d'un flux PeekableInputStream ici:

http://www.heatonresearch.com/articles/147/page2.html

L’idée de l’implémentation montrée dans l’article est qu’elle conserve un tableau de "regard". valeurs en interne. Lorsque vous appelez read, les valeurs sont d'abord renvoyées par le tableau visualisé, puis par le flux d'entrée. Lorsque vous appelez peek, les valeurs sont lues et stockées dans le répertoire "peeked". tableau.

La licence de l'exemple de code étant LGPL, vous pouvez la joindre à ce message:

package com.heatonresearch.httprecipes.html;

import java.io.*;

/**
 * The Heaton Research Spider Copyright 2007 by Heaton
 * Research, Inc.
 * 
 * HTTP Programming Recipes for Java ISBN: 0-9773206-6-9
 * http://www.heatonresearch.com/articles/series/16/
 * 
 * PeekableInputStream: This is a special input stream that
 * allows the program to peek one or more characters ahead
 * in the file.
 * 
 * This class is released under the:
 * GNU Lesser General Public License (LGPL)
 * http://www.gnu.org/copyleft/lesser.html
 * 
 * @author Jeff Heaton
 * @version 1.1
 */
public class PeekableInputStream extends InputStream
{

  /**
   * The underlying stream.
   */
  private InputStream stream;

  /**
   * Bytes that have been peeked at.
   */
  private byte peekBytes[];

  /**
   * How many bytes have been peeked at.
   */
  private int peekLength;

  /**
   * The constructor accepts an InputStream to setup the
   * object.
   * 
   * @param is
   *          The InputStream to parse.
   */
  public PeekableInputStream(InputStream is)
  {
    this.stream = is;
    this.peekBytes = new byte[10];
    this.peekLength = 0;
  }

  /**
   * Peek at the next character from the stream.
   * 
   * @return The next character.
   * @throws IOException
   *           If an I/O exception occurs.
   */
  public int peek() throws IOException
  {
    return peek(0);
  }

  /**
   * Peek at a specified depth.
   * 
   * @param depth
   *          The depth to check.
   * @return The character peeked at.
   * @throws IOException
   *           If an I/O exception occurs.
   */
  public int peek(int depth) throws IOException
  {
    // does the size of the peek buffer need to be extended?
    if (this.peekBytes.length <= depth)
    {
      byte temp[] = new byte[depth + 10];
      for (int i = 0; i < this.peekBytes.length; i++)
      {
        temp[i] = this.peekBytes[i];
      }
      this.peekBytes = temp;
    }

    // does more data need to be read?
    if (depth >= this.peekLength)
    {
      int offset = this.peekLength;
      int length = (depth - this.peekLength) + 1;
      int lengthRead = this.stream.read(this.peekBytes, offset, length);

      if (lengthRead == -1)
      {
        return -1;
      }

      this.peekLength = depth + 1;
    }

    return this.peekBytes[depth];
  }

  /*
   * Read a single byte from the stream. @throws IOException
   * If an I/O exception occurs. @return The character that
   * was read from the stream.
   */
  @Override
  public int read() throws IOException
  {
    if (this.peekLength == 0)
    {
      return this.stream.read();
    }

    int result = this.peekBytes[0];
    this.peekLength--;
    for (int i = 0; i < this.peekLength; i++)
    {
      this.peekBytes[i] = this.peekBytes[i + 1];
    }

    return result;
  }

}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top