代码之家  ›  专栏  ›  技术社区  ›  Epaga Alex Reynolds

如何查看输入流中的前两个字节?

  •  29
  • Epaga Alex Reynolds  · 技术社区  · 17 年前

    应该很简单:我有一个inputstream,我想查看(而不是读取)前两个字节,也就是说,我希望inputstream的“当前位置”在我查看后仍然为0。这样做的最好和最安全的方法是什么?

    回答 -正如我所怀疑的,解决方案是将它包装在一个提供标记性的缓冲输入流中。谢谢拉斯姆斯。

    4 回复  |  直到 14 年前
        1
  •  49
  •   Rasmus Faber    17 年前

    对于一般的inputstream,我将它包装在一个bufferedinputstream中,并执行如下操作:

    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
    
        2
  •  16
  •   Juuso Ohtonen    14 年前

    您可能会发现pushbackinputstream非常有用:

    http://docs.oracle.com/javase/6/docs/api/java/io/PushbackInputStream.html

        3
  •  5
  •   Dr. Xray    17 年前

    使用BufferedInputStream时,请确保尚未对输入流进行缓冲,双缓冲将导致一些严重的难以找到的错误。 此外,您还需要以不同的方式处理读卡器,如果对读卡器进行缓冲,转换为流读卡器和缓冲将导致字节丢失。 另外,如果您使用的是读卡器,请记住您不是在读取字节,而是在默认编码中读取字符(除非设置了显式编码)。 您可能不知道的缓冲输入流示例是url url;url.openstream();

    我没有此信息的任何引用,它来自调试代码。 我遇到的主要问题是从文件读取到压缩流的代码。 如果我记得正确,一旦你开始调试代码,有评论在Java源,某些事情不能正常工作。 我不记得使用BufferedReader和BufferedInputStream的信息在哪里 来自,但我认为即使在最简单的测试中,也会直接失败。 记住,要测试这一点,您需要标记的缓冲区大小(BufferedReader和BufferedInputStream的大小不同),当被读取的字节到达缓冲区的末尾时,就会出现问题。 注意,有一个源代码缓冲区大小,它可能与您在构造函数中设置的缓冲区大小不同。 我做这件事已经有一段时间了,所以我对细节的记忆可能有点模糊了。 测试是使用filterreader/filterinputstream完成的,将一个添加到直接流,一个添加到缓冲流以查看差异。

        4
  •  4
  •   Mario Ortegón    17 年前

    我在这里找到了一个peekableinputstream的实现:

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

    本文中所示的实现的思想是,它在内部保留一个“peeked”值数组。当调用read时,首先从被偷看的数组返回值,然后从输入流返回值。当您调用peek时,这些值将被读取并存储在“peek”数组中。

    由于示例代码的许可证是lgpl,因此可以将其附加到此日志:

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