XMLStreamReader не закрывает открытый xml-файл

для использования XMLStreamReader я инициализирую его как -

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

итерация над ним, как -

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

наконец-то это нравится -

reader.close();

это выглядит как нормальный поток, но я вижу какое-то странное поведение. Даже после закрытия reader ОС не позволяет мне удалять / перемещать xml-файл, если я не выхожу из java-программы. При запуске на Win2k8-сервере я получаю сообщение об ошибке java.exe использует этот xml-файл.

Итак, у меня есть пара вопросы -

  1. нужно ли явно закрывать закрытие каждого FileReader?
  2. как я могу узнать, какой путь кода java держит этот дескриптор файла открытым.

глядя @ документацию xmlstreamreader close (), я получаю следующее - "освобождает любые ресурсы, связанные с этим читателем. Этот метод не закрывает базовый источник ввода."

что означает "базовый источник ввода"? Почему это не закрыто читателя закрыть()?

2 ответов


базовый источник ввода, упомянутый в документе, - это именно то, что вы должны закрыть. Поместите FileReader в локальную переменную, чтобы закрыть ее:

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

что означает "базовый источник ввода"? Почему это не закрыто reader's close ()?

Вы создали XMLReader с помощью XMLInputFactory.createXMLStreamReader с аргументом InputStream или около того. Это "базовый источник ввода". :) Поскольку он открылся за пределами XMLReader, таким образом, XMLReader не закроет его. Но, если вам нужно, можете использовать этот класс-оболочку для XMLReader. Просто работать.

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);
        }
    }
}