【问题标题】:Prevent file channel from closing after reading xml file防止读取xml文件后关闭文件通道
【发布时间】:2014-12-23 16:48:50
【问题描述】:

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

  1. 获得对 xml 文件的独占文件锁定。
  2. 将文件读入Document 对象。
  3. 进行任意更改(锁定仍处于活动状态!)。
  4. 将更改写回 xml 文件。
  5. 释放文件锁定。

然而,我遇到的问题是将 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 库,我真的很难找到通道关闭的位置,更不用说如何防止它关闭了。任何指针都会很棒!谢谢。

【问题讨论】:

  • DocumentBuilder.parse() 正在关闭提供的输入流。
  • 抱歉这个问题有点误导,我的意思是我无法弄清楚内置的 DocumentBuilder 类在哪里关闭了通道以覆盖行为。覆盖FilterInputStream(正如接受的答案所做的那样)的默认关闭行为似乎可以达到相同的结果。

标签: java xml concurrency io channel


【解决方案1】:

您尝试过try-with-ressource 语句吗?即使,这不是这个功能的主要目的,也许这就是你想要的(以自动关闭资源(你的频道)的形式,但只有当你离开相应的 try-block 时)

try (final Channel channel = new RandomAccessFile(new File(path), "rw").getChannel()) {
  // your stuff here
} catch (IOException ex) {
  ex.printStackTrace();
}

【讨论】:

  • 您好,感谢您的回复。不幸的是,我只是尝试了这个,但它似乎没有什么效果。不过它看起来有点干净,所以我可能还是会保留它!
  • 这会关闭频道。这正是他试图防止的。请阅读这个问题。
  • @EJP 我知道关闭(请阅读我的答案),我只是将其作为在调用dBuilder.parse() 后保持锁定的想法,这是 OP 的需要。请阅读问题。
【解决方案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();
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2014-10-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-03-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多