有关此目标的动机的详细信息,请查看我的previous question。我(再次)决定完全将这个问题作为一个新问题,因为我认为它已经发展到足够值得这样做。总而言之,我打算将JDOM与NIO结合使用,以便:
通过覆盖FilterInputStream
的关闭行为解决了an issue with reading the xml file via a channel,我现在有一个锁定的频道,我可以使用Transformer.transform()
写入。但问题是,Transformer.Transform
不是替换原始文件,而是将新文件附加到原始文件的末尾而不是替换它(参见图像)。
问题不在于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)
答案 0 :(得分:1)
这几乎肯定会发生,因为您的频道在阅读后会定位在文件的末尾。
在执行转换之前,您应该能够通过执行以下操作来解决此问题:
channel.truncate(0);
这应该将文件截断为0并将位置重置为0.
http://docs.oracle.com/javase/7/docs/api/java/nio/channels/FileChannel.html#truncate(long)