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?
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With