1
votes

I have an InputStream which contains XML data which I would like to parse before returning the InputStream.

InputStream is = myObj.getInputStream();

// parse Inputstream here

return is;

Of course I could save the stream as a byte array and return a new InputStream from that or

create a second InputStream on 'myObj'.

But is there any way to parse the stream 'on the fly'?

Edit:

Basically I am searching for a way to re-use the stream after parsing. Sort of parsing the stream without consuming it, respectively to reset it after the parsing.

Solution:

The solution I've found is to use a BufferedInputStream (Note from the comments: That will only work up to 8k bytes)

BufferedInputStream is = new BufferedInputStream ( myObj.getInputStream() );

is.mark( Integer.MIN_VALUE );

// parse Inputstream here

is.reset();

return is;

3

3 Answers

2
votes

To parse on the fly, without waiting the end of stream you can use a Sax Parser.

A sax parser is event based so it is not necessary to read the whole document before processing it. With that the process is something like:

  • THe tag person is open
  • The tag name is open
  • The tag name is closed
  • the tag surname is opened
  • the tag surname is closed
  • the tag person is closed

For each event you need to execute some custom code.

Working with a sax parser is a little more difficult than a dom parser but has some advantages. Over all it needs less resources and you don't need to wait to have the whole document.

0
votes

This can be quite complicated because the best candidate for on-the-fly xml parsing the SAX Parser. By necessity it is event driven and relies on callback methods to indicate events in the incoming stream.

I have implemented something like this by doing the following:

  1. Create a Queue.
  2. Fire off a thread that parses the XML using the SAXParser pushing the results into the Queue.
  3. Iterate over the queue.

This is not simple but it is stable and reliable. I will try to post some demo code.

-1
votes

The solution I've found (at least the one that works for me) is to use a BufferedInputStream:

BufferedInputStream is = new BufferedInputStream ( myObj.getInputStream() );

is.mark( Integer.MIN_VALUE );

// parse Inputstream here

is.reset();

return is;