4

假设我有以下 XML 文件:

<book>
 <name>sometext</name>
 <name>sometext</name>
 <name>sometext</name>
 <name>Dometext</name>
 <name>sometext</name>
</book> 

如果我想通过将 D 更改为 s 来修改内容(如第四个“名称”节点所示)而不必读/写整个文件,这可能吗?

4

4 回答 4

3

10 MB 的文件不是问题。啜饮它。修改 DOM。将其写回文件系统。10 GB 更成问题。在这种情况下:

假设:您没有更改文件的长度。将文件视为字符数组而不是(链接的)字符列表:您不能在中间添加字符,只能更改它们。

您需要seek更改文件中的位置,然后write将该字符写入磁盘。

在 .NET 世界中,使用FileStream对象,您将Position属性设置为字符的索引,D然后写入单个s字符。查看有关随机访问文本文件的这个问题

另请阅读此问题:如何使用 C# 将字符插入文件。看起来您不能真正使用该FileStream对象,而是不得不求助于写入单个字节。

祝你好运。但实际上,如果我们只谈论 10 MB,那么就大吃一惊。计算机应该在做你的工作。

于 2011-10-13T08:37:44.993 回答
2

我只是读入文件,处理,然后再吐出来。

这可以使用XmlReader以流方式完成——它比 XmlDocument 或 XDocument 需要更多的手动工作,但它确实避免了创建内存中的 DOM(XmlDocument/XDocument 可以与相同的读/写模式一起使用,但通常需要内存中的完全重建):

  1. 打开文件输入文件流(XmlReader)
  2. 打开输出文件流(XmlWriter,到不同的文件
  3. 从 XmlReader 读取并写入 XmlWriter,根据需要执行任何转换。
  4. 关闭流
  5. 将新文件移动到旧文件(覆盖,原子操作)

虽然这可以设置为处理同一个打开文件上的输入和输出,但需要进行大量非常聪明的工作,但不会保存任何内容,并且存在许多边缘情况,包括随着文件长度的减少而增加。事实上,尝试简单地向后移动文件内容以填补空白或向前移动文件内容以腾出新空间可能会更慢。除了最基本的长度保持操作之外,文件系统缓存可能会使任何“增益”最小/没有意义。此外,就地修改文件不是原子操作,并且在发生错误时通常是不可恢复的:以临时文件为代价,读/写/移动方法是最终文件内容的原子操作。

或者,考虑一下XSLT——它就是为此而设计的 ;-)

快乐编码。

于 2011-10-13T08:40:36.940 回答
1

最干净(也是最好)的方法是使用 XmlDocument 对象进行操作,但一个快速而肮脏的解决方案是将 XML 读取为字符串,然后:

xmlText = xmlText.Replace("Dometext", "sometext");
于 2011-10-13T08:23:48.373 回答
1

XML 文件是文本文件,不允许插入/删除。唯一支持的突变是 OverWrite 和 Append。不适合 XML。

所以,首先要确定你真的需要这个。这是一项复杂的操作,仅在非常大的文件上才值得。

由于长度可能会发生变化,因此您至少必须在第一次更换后移动所有内容。多次替换的可能性意味着您可能需要一个大缓冲区来适应更改。

复制整个文件更容易。这在 I/O 方面很昂贵,但可以节省内存使用量。

于 2011-10-13T08:39:42.727 回答