Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Does DocumentBuilder.parse close the InputStream

For code similar to the following:

InputStream is = new FileInputstream("test.xml");
Document doc = DocumentBuilder.parser(is);

My question is whether I need to close the stream manually (invoke is.close()). Does DocumentBuilder close the InputStream for me?

like image 884
Jeff Fang Avatar asked Mar 06 '12 06:03

Jeff Fang


1 Answers

Use the following test code to see whether the input stream is closed or not, and you could see which line of code closes the stream.

public class DocumentBuilderTest {

 public static void main(String[] args) {
   try {
     InputStream is = new MyInputStream("project.xml");
     DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
     DocumentBuilder documentBuilder = dbf.newDocumentBuilder();
     documentBuilder.parse(is);
   } catch (Exception e) {
     e.printStackTrace();
   }
 }

 static class MyInputStream extends FileInputStream {   
   public MyInputStream(String filename) throws FileNotFoundException {
     super(filename);
   }

   @Override
   public void close() throws IOException {
     // here we log when the stream is close.
     System.out.println("file input stream closed.");
     Exception e = new Exception();
     e.printStackTrace();
     super.close();
   }

 }
}

Whether the input stream passed to the DocumentBuilder is closed or not depends on the DOMParser implementation. In my environment, the file input stream is closed, see the stack trace below:

at DocumentBuilderTest$MyInputStream.close(DocumentBuilderTest.java:37)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager$RewindableInputStream.close(XMLEntityManager.java:3047)
at com.sun.org.apache.xerces.internal.impl.io.UTF8Reader.close(UTF8Reader.java:661)
at com.sun.xml.internal.stream.Entity$ScannedEntity.close(Entity.java:441)
at com.sun.org.apache.xerces.internal.impl.XMLEntityManager.endEntity(XMLEntityManager.java:1406)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.load(XMLEntityScanner.java:1763)
at com.sun.org.apache.xerces.internal.impl.XMLEntityScanner.skipSpaces(XMLEntityScanner.java:1543)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl$TrailingMiscDriver.next(XMLDocumentScannerImpl.java:1400)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentScannerImpl.next(XMLDocumentScannerImpl.java:648)
at com.sun.org.apache.xerces.internal.impl.XMLDocumentFragmentScannerImpl.scanDocument(XMLDocumentFragmentScannerImpl.java:511)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:808)
at com.sun.org.apache.xerces.internal.parsers.XML11Configuration.parse(XML11Configuration.java:737)
at com.sun.org.apache.xerces.internal.parsers.XMLParser.parse(XMLParser.java:119)
at com.sun.org.apache.xerces.internal.parsers.DOMParser.parse(DOMParser.java:235)
at com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderImpl.parse(DocumentBuilderImpl.java:284)
at javax.xml.parsers.DocumentBuilder.parse(DocumentBuilder.java:124)
at DocumentBuilderTest.main(DocumentBuilderTest.java:22)

So you could not manually close the stream in this specific example. However, it is always a good idea to close input stream when you are sure that the stream will not be used any more. In your case, once the document is parsed, the input stream is no longer needed, so the stream could be safely closed, and I suggest you do that.

like image 56
Mingjiang Shi Avatar answered Oct 16 '22 13:10

Mingjiang Shi