Xml附加到文件末尾而不是替换文件

时间:2014-10-29 09:39:01

标签: java xml dom channel file-locking

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

  1. 获取xml文件的独占文件锁。
  2. 将文件读入Document对象。
  3. 进行任意更改(锁定仍处于活动状态!)。
  4. 将更改写回xml文件。
  5. 释放文件锁。
  6. 通过覆盖FilterInputStream的关闭行为解决了an issue with reading the xml file via a channel,我现在有一个锁定的频道,我可以使用Transformer.transform()写入。但问题是,Transformer.Transform不是替换原始文件,而是将新文件附加到原始文件的末尾而不是替换它(参见图像)。

    enter image description here

    问题不在于Document对象本身,可以通过使用Document对象作为输入打印从以下方法返回的字符串来看到:

    public String toXMLString(Node node) {
        try {
            this.removeBlankTextNodes(node);
            StringWriter sw = new StringWriter();
            TransformerFactory tf = TransformerFactory.newInstance();
            Transformer transformer = tf.newTransformer();
            transformer.transform(new DOMSource(node), new StreamResult(sw));
            return sw.toString();
        } catch (TransformerException ex) {
            throw new RuntimeException("Error converting to String", ex);
        }
    }
    

    当为同一文件建立新频道并将其用作result的{​​{1}}时,也不会出现追加问题。因此,只有在使用相同的频道进行读写时才会出现此问题(这可能就是为什么他们选择在调用Transformer.transform()时自动关闭频道。

    我已经彻底检查了文档,找不到任何相关的选项来指定Transformer.transform的输出(我搜索过Transformer / Transformer factory / StreamResult),虽然因为很多类都是抽象的,所以我很难找到实际的实施代码。在调试器中检查DocumentBuilder.parse()对象时,实际上看起来append选项设置为false,所以我主要怀疑在读取操作完成后我需要以某种方式清除通道(或相关的缓冲区?) 。我尝试的最后一件事是使用代码StreamResult打开频道,除了“APPEND”之外几乎所有选项;这再次没有效果。请注意,我不能只关闭并重新打开通道,因为这将释放文件锁定。任何指针/建议都会很棒!代码如下:

    channel.open(Paths.get(path), StandardOpenOption.CREATE)

1 个答案:

答案 0 :(得分:1)

这几乎肯定会发生,因为您的频道在阅读后会定位在文件的末尾。

在执行转换之前,您应该能够通过执行以下操作来解决此问题:

channel.truncate(0);

这应该将文件截断为0并将位置重置为0.

http://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileChannel.html#truncate(long)