PDA

View Full Version : Seeking possible in Java streams?



Habbit
September 8th, 2008, 02:25 AM
Hi there,

I'm facing a problem I had not anticipated in the design of "input plugins" for a Java application. This plugins have the general structure of a canRead method that, given an InputStream, tries to guess whether that particular class can parse the whole stream; and methods to actually perform the import.

However, the point is that the canRead method should, if possible, leave the Stream effectively untouched, i.e. in the same position. I have noticed that there is no "seek" method in Java input streams; I had assumed there would be by similarity with .NET streams, but it seems that I am wrong. Googling for it shows nearly nothing, and maybe the solution is obvious because the question was only asked a few times in thousands of results. Some of the solutions I've been offered include the usage of file-input-specific classes such as RandomAccessFile or FileChannel in the java.nio package (that I don't understand too well o_O), but I don't want to limit myself to files, as "memory streams" can be sources for my "plugins" too.

Thus, how could I, given a simple InputStream, know whether or not it can seek (and do it if possible)?. As an example of what I want, this would be the equivalent c# code:

public bool CanRead(Stream is) {
bool retVal;
long startPos = is.CanSeek ? is.Position : -1;

// Check whether this plugin can parse "is" - read from it

if (is.CanSeek)
is.Position = startPos;
return retVal;
}

tinny
September 8th, 2008, 07:53 AM
I believe you want to have a look at the InputStream classes "markSupported()", "mark(int readlimit)" and "reset()" methods.

http://java.sun.com/j2se/1.5.0/docs/api/java/io/InputStream.html

E.g. your implementation may look something like this...



/**
* Check if a supplied input stream can be parsed.
* @param is input stream
* @return true if it can be parsed
*/
public boolean canParse(InputStream is) throws IOException {
boolean result = false;
//Check if this stream can be inspected
if (is.markSupported()) {
is.mark(Integer.MAX_VALUE);
// Check whether this plugin can parse "is" - read from it
result = inspect(is);
is.reset();
} else {
//Cant predit
result = false;
}
return result;
}

/**
* Inspect this steam to check if it can be parsed.
* @param is
* @return true if this stream can be parsed.
*/
private boolean inspect(InputStream is) {
//Now read whatever you need to from the stream to determine if your
//class can parse this stream.
//E.g.
//is.read();
//is.read(arg0);
//is.skip(arg0);
//is.available();
//etc...
return true; //can parse
//return false cant parse
}


Hope this helps :)

Habbit
September 8th, 2008, 11:11 AM
Sorry, I forgot to mention that I had already looked into the mark and reset methods. They look more or less like what I want, but FileInputStream does not support them in "Java 5" or the OpenJDK (***??). Thus, they are useless to me becase they'd force me to change the prototype of canRead to accept only BufferedInputStream. Thanks anyway :KS