[ACCEPTED]-How do I peek at the first two bytes in an InputStream?-bufferedinputstream
For a general InputStream, I would wrap 2 it in a BufferedInputStream and do something 1 like this:
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
You might find PushbackInputStream to be 1 useful:
http://docs.oracle.com/javase/6/docs/api/java/io/PushbackInputStream.html
When using a BufferedInputStream make sure 35 that the inputStream is not already buffered, double 34 buffering will cause some seriously hard 33 to find bugs. Also you need to handle Readers 32 differently, converting to a StreamReader 31 and Buffering will cause bytes to be lost 30 if the Reader is Buffered. Also if you 29 are using a Reader remember that you are 28 not reading bytes but characters in the 27 default encoding (unless an explicit encoding 26 was set). An example of a buffered input 25 stream, that you may not know is URL url; url.openStream();
I 24 do not have any references for this information, it 23 comes from debugging code. The main case 22 where the issue occurred for me was in code 21 that read from a file into a compressed 20 stream. If I remember correctly once you 19 start debugging through the code there are 18 comments in the Java source that certain 17 things do not work correctly always. I do 16 not remember where the information from 15 using BufferedReader and BufferedInputStream comes 14 from but I think that fails straight away 13 on even the simplest test. Remember to test 12 this you need to be marking more than the 11 buffer size (which is different for BufferedReader 10 versus BufferedInputStream), the problems 9 occur when the bytes being read reach the 8 end of the buffer. Note there is a source 7 code buffer size which can be different 6 to the buffer size you set in the constructor. It 5 is a while since I did this so my recollections 4 of details may be a little off. Testing 3 was done using a FilterReader/FilterInputStream, add 2 one to the direct stream and one to the 1 buffered stream to see the difference.
I found an implementation of a PeekableInputStream 9 here:
http://www.heatonresearch.com/articles/147/page2.html
The idea of the implementation shown 8 in the article is that it keeps an array 7 of "peeked" values internally. When 6 you call read, the values are returned first 5 from the peeked array, then from the input 4 stream. When you call peek, the values 3 are read and stored in the "peeked" array.
As 2 the license of the sample code is LGPL, It 1 can be attached to this post:
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;
}
}
More Related questions
We use cookies to improve the performance of the site. By staying on our site, you agree to the terms of use of cookies.