Предотвратить закрытие файлового канала после прочтения XML-файла
Для получения более подробной информации о мотивации этой цели (и моих усилиях по ее решению) просмотрите мой предыдущий вопрос. Я решил задать это как новый вопрос полностью, так как думал, что он эволюционировал достаточно, чтобы заслужить это. Таким образом, я намерен использовать JDOM в сочетании с NIO для того, чтобы:
- Получите эксклюзивную блокировку файла на XML-файл.
- Прочитайте файл в
Document
объект. - Произведите произвольные изменения (с активной блокировкой!).
- Запишите изменения обратно в XML-файл.
- Снимите блокировку файла.
Однако проблема, которую я получаю, заключается в том, что встроенный код для чтения файла xml в объект документа закрывает канал (и, следовательно, снимает блокировку), как показано ниже:
import java.io.*;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import javax.xml.parsers.*;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;
public class Test4{
String path = "Test 2.xml";
private DocumentBuilderFactory dbFactory;
private DocumentBuilder dBuilder;
private Document doc;
public Test4(){
try (final FileChannel channel = new RandomAccessFile(new File(path), "rw").getChannel()) {
dbFactory = DocumentBuilderFactory.newInstance();
dBuilder = dbFactory.newDocumentBuilder();
System.out.println(channel.isOpen());
doc = dBuilder.parse(Channels.newInputStream(channel));
System.out.println(channel.isOpen());
channel.close();
} catch (IOException | ParserConfigurationException | SAXException e) {
e.printStackTrace();
}
}
public static void main(String[] args){
new Test4();
}
}
Выход:
true
false
Просматривая документацию и просматривая встроенные библиотеки Java, я действительно изо всех сил пытаюсь даже найти, где канал закрыт, не говоря уже о том, как предотвратить его закрытие. Любые указатели были бы великолепны! Благодарю.
2 ответа
Один чистый способ сделать это - создать FilterInputStream
и переопределить close
ничего не делать:
public Test() {
try {
channel = new RandomAccessFile(new File(path), "rw").getChannel();
dbFactory = DocumentBuilderFactory.newInstance();
dBuilder = dbFactory.newDocumentBuilder();
System.out.println(channel.isOpen());
NonClosingInputStream ncis = new NonClosingInputStream(Channels.newInputStream(channel));
doc = dBuilder.parse(ncis);
System.out.println(channel.isOpen());
// Closes here.
ncis.reallyClose();
channel.close(); //Redundant
} catch (IOException | ParserConfigurationException | SAXException e) {
e.printStackTrace();
}
}
class NonClosingInputStream extends FilterInputStream {
public NonClosingInputStream(InputStream it) {
super(it);
}
@Override
public void close() throws IOException {
// Do nothing.
}
public void reallyClose() throws IOException {
// Actually close.
in.close();
}
}
Вы пробовали оценку " попробуй с ресурсом"? Несмотря на то, что это не основная цель этой функции, возможно, она делает то, что вы ищете (в форме автоматического закрытия ресурсов (вашего канала), но только когда вы выходите из соответствующего блока try)
try (final Channel channel = new RandomAccessFile(new File(path), "rw").getChannel()) {
// your stuff here
} catch (IOException ex) {
ex.printStackTrace();
}