Java 防止读取xml文件后关闭文件通道

Java 防止读取xml文件后关闭文件通道,java,xml,concurrency,io,channel,Java,Xml,Concurrency,Io,Channel,有关此目标背后动机(以及我为解决此目标所做的努力)的更多详细信息,请查看我的。我决定把这个问题作为一个全新的问题提出,因为我认为它已经发展到值得这样做的程度。作为总结,我打算将JDOM与NIO结合使用,以便: 获取xml文件的独占文件锁定 将文件读入文档对象 进行任意更改(锁定仍处于活动状态!) 将更改写回xml文件 释放文件锁 但是,我遇到的问题是,将xml文件读入文档对象的内置代码会关闭通道(从而释放锁),如下所示: import java.io.*; import java.nio.cha

有关此目标背后动机(以及我为解决此目标所做的努力)的更多详细信息,请查看我的。我决定把这个问题作为一个全新的问题提出,因为我认为它已经发展到值得这样做的程度。作为总结,我打算将JDOM与NIO结合使用,以便:

  • 获取xml文件的独占文件锁定
  • 将文件读入
    文档
    对象
  • 进行任意更改(锁定仍处于活动状态!)
  • 将更改写回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库之后,我真的很难找到通道关闭的位置,更不用说如何防止它关闭了。任何指针都会很棒!谢谢。

    你试过这个座位了吗?尽管这并不是此功能的主要目的,但这可能正是您想要的(以自动关闭资源(您的频道)的形式,但仅当您离开相应的try块时)


    一种干净的方法是创建一个
    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();
        }
    }
    

    你好,谢谢你的回复。不幸的是,我只是尝试了一下,但效果似乎不大。虽然看起来有点干净,但我还是会保留它的!这将关闭通道。这正是他想要阻止的。一定要读这个问题。@EJP我知道结束了(一定要读我的答案),我只是想在调用
    dBuilder.parse()
    后保留锁,这是OP需要的。请务必阅读此问题。
    DocumentBuilder.parse()
    正在关闭提供的输入流。很抱歉,此问题有点误导,我的意思是我无法确定内置DocumentBuilder类在何处关闭通道以覆盖该行为。不过,覆盖
    FilterInputStream
    的默认关闭行为(与接受的答案一样)似乎可以获得相同的结果。
    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();
        }
    }