XMLStreamReader not closing opened xml file
Asked Answered
A

2

7

To use XMLStreamReader I am initializing it like -

XMLInputFactory f = XMLInputFactory.newInstance();
XMLStreamReader reader = f.createXMLStreamReader(new FileReader(
        "somefile.xml"));

Iterating over it like -

if (reader.hasNext()) {
    reader.next();
    // do something with xml data
}

Finally closing it like -

reader.close();

This looks to be a normal flow but I am seeing some strange behavior. Even after closing reader, OS doesn't allow me delete/move the xml file unless I exit from java program. When run on Win2k8-server, I get error message saying java.exe is using this xml file.

So I have couple of questions -

  1. Do I need to explicitly close each FileReader's close?
  2. How can I find out which java code path is keeping this file handle open.

Looking @ the documentation of XMLStreamReader's close(), I get following - "Frees any resources associated with this Reader. This method does not close the underlying input source."

What is the meaning of "underlying input source"? Why is that not closed by reader's close()?

Arlyn answered 7/5, 2011 at 12:22 Comment(0)
P
11

The underlying input source mentioned in the doc is exactly what you should close. Put the FileReader into a local variable to be able to close it:

XMLInputFactory f = XMLInputFactory.newInstance();
FileReader fr = new FileReader("somefile.xml");
XMLStreamReader reader = f.createXMLStreamReader(fr);

// process xml

reader.close();
fr.close();

//suggest using apache commons IOUtils.closeQuietly(fr); this way you
// don't have to deal with exceptions if you don't want
Punchinello answered 7/5, 2011 at 12:26 Comment(2)
The API of the close() method clearly say that it does not close the underlying Reader object. Maybe quote the sentence from the API in your answer.Enkindle
Anything on my second question - How can I find out which java code path is keeping this file handle open?Arlyn
R
2

What is the meaning of "underlying input source"? Why is that not closed by reader's close()?

You created XMLReader by XMLInputFactory.createXMLStreamReader with argument InputStream or so. This is an "underlying input source". :) Because it opened outside of XMLReader, thus XMLReader will not close it. But, if you need, can use this wrapper class for XMLReader. Just works.

import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.util.StreamReaderDelegate;

public class XMLFileReader extends StreamReaderDelegate implements AutoCloseable {
    private final static XMLInputFactory factory = XMLInputFactory.newFactory();
    private final Path file;
    private final InputStream stream;
    private final XMLStreamReader reader;

    public XMLFileReader(Path file) throws IOException, XMLStreamException {
        super();
        this.file = file;
        stream = Files.newInputStream(this.file);
        reader = factory.createXMLStreamReader(stream);
        setParent(reader);
    }

    @Override
    public void close() throws XMLStreamException {
        try {
            super.close();
            stream.close();
        } catch (IOException e) {
            throw new XMLStreamException(file+" : "+e.getMessage(),e);
        }
    }
}
Randle answered 14/2, 2018 at 18:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.