应该很简单:我有一个InputStream,我希望偷看(不读取)前两个字节,即我希望InputStream的“当前位置”在我窥视后仍为0。什么是最好和最安全的方法来做到这一点?如何查看InputStream中的前两个字节?
答案 - 正如我所怀疑的,解决方案是将其包装在提供可标记性的BufferedInputStream中。谢谢Rasmus。
应该很简单:我有一个InputStream,我希望偷看(不读取)前两个字节,即我希望InputStream的“当前位置”在我窥视后仍为0。什么是最好和最安全的方法来做到这一点?如何查看InputStream中的前两个字节?
答案 - 正如我所怀疑的,解决方案是将其包装在提供可标记性的BufferedInputStream中。谢谢Rasmus。
对于一般的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
我发现了一个PeekableInputStream这里的实现:
http://www.heatonresearch.com/articles/147/page2.html
的想法文章中显示的实现是它在内部保留一组“窥视”值。当你调用read时,首先从peeked数组返回值,然后从输入流返回值。当你调用peek时,这些值将被读取并存储在“peeked”数组中。
由于样本代码的许可证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;
}
}
当使用的BufferedInputStream确保InputStream的尚未缓冲,双缓冲会导致一些严重的硬找到错误。 此外,您需要以不同的方式处理读者,转换为StreamReader并且缓冲器会导致字节在读者缓冲时丢失。 另外,如果您使用的是Reader,请记住您不是读取字节,而是使用默认编码中的字符(除非设置了明确的编码)。 一个缓冲输入流的例子,你可能不知道的是URL url; url.openStream();
我没有任何关于此信息的参考,它来自调试代码。 问题发生在我身上的主要情况是在从文件读入压缩流的代码中。 如果我没有记错,一旦你开始通过代码进行调试,那么在Java源代码中有一些评论说某些事情总是无法正常工作。 我不记得使用BufferedReader和BufferedInputStream 的信息来自哪里,但我认为即使是最简单的测试也会失败。 记住要测试这个,你需要标记的不止是缓冲区的大小(BufferedReader与BufferedInputStream的不同),当读取的字节到达缓冲区的末尾时会出现问题。 请注意,源代码缓冲区大小可能与您在构造函数中设置的缓冲区大小不同。 这是一段时间,因为我这样做,所以我对细节的回忆可能有点关闭。 使用FilterReader/FilterInputStream完成测试,将一个添加到直接流,一个添加到缓冲流以查看差异。
有趣!你有没有关于双缓冲和BufferedInputStream与InputStreamReader相结合的问题的任何细节? Google找不到任何内容。 – 2008-09-29 10:44:35
您可能会发现PushbackInputStream是有用的:
http://docs.oracle.com/javase/6/docs/api/java/io/PushbackInputStream.html
参见http://java.sun.com/javase/6/docs/api/java/io/InputStream.html#markSupported( ) – McDowell 2008-09-29 10:13:40
作品像魅力,谢谢! – Epaga 2008-09-29 10:31:34