我想以紧凑的格式将 xml 文档写入磁盘。为此,我使用了net framework方法XmlDictionaryWriter.CreateBinaryWriter(Stream stream,IXmlDictionary dictionary)
此方法编写一个自定义的紧凑二进制 xml 表示,以后可以由XmlDictionaryWriter.CreateBinaryReader
. 该方法接受一个XmlDictionary
可以包含公共字符串的字符串,这样就不必每次都在输出中打印这些字符串。字典索引将打印在文件中,而不是字符串。CreateBinaryReader
以后可以使用相同的字典来反转该过程。
但是我通过的字典显然没有使用。考虑这段代码:
using System.IO;
using System.Xml;
using System.Xml.Linq;
class Program
{
public static void Main()
{
XmlDictionary dict = new XmlDictionary();
dict.Add("myLongRoot");
dict.Add("myLongAttribute");
dict.Add("myLongValue");
dict.Add("myLongChild");
dict.Add("myLongText");
XDocument xdoc = new XDocument();
xdoc.Add(new XElement("myLongRoot",
new XAttribute("myLongAttribute", "myLongValue"),
new XElement("myLongChild", "myLongText"),
new XElement("myLongChild", "myLongText"),
new XElement("myLongChild", "myLongText")
));
using (Stream stream = File.Create("binaryXml.txt"))
using (var writer = XmlDictionaryWriter.CreateBinaryWriter(stream, dict))
{
xdoc.WriteTo(writer);
}
}
}
产生的输出是这样的(未显示二进制控制字符)
@
myLongRootmyLongAttribute˜myLongValue@myLongChild™
myLongText@myLongChild™
myLongText@myLongChild™
myLongText
所以显然 XmlDictionary 没有被使用。所有字符串都完整地出现在输出中,甚至多次出现。
这不是仅限于 XDocument 的问题。在上面的最小示例中,我使用 XDocument 来演示问题,但最初我在使用 XmlDictionaryWriter 和 DataContractSerializer 时偶然发现了这一点,因为它是常用的。结果是一样的:
[Serializable]
public class myLongChild
{
public double myLongText = 0;
}
...
using (Stream stream = File.Create("binaryXml.txt"))
using (var writer = XmlDictionaryWriter.CreateBinaryWriter(stream, dict))
{
var dcs = new DataContractSerializer(typeof(myLongChild));
dcs.WriteObject(writer, new myLongChild());
}
结果输出没有使用我的 XmlDictionary。
如何让 XmlDictionaryWriter 使用提供的 XmlDictionary?
还是我误解了它是如何工作的?
使用 DataContractSerializer 方法,我尝试调试网络框架代码(visual studio/options/debugging/enable net.framework source stepping)。显然,作家确实尝试在字典中查找上述每个字符串,正如预期的那样。但是,由于我不清楚的原因,在XmlbinaryWriter.cs 的第 356 行查找失败。
我考虑过的替代方案:
XmlDictionaryWriter.CreatebinaryWriter 有一个重载,它也接受 XmlBinaryWriterSession。然后编写器将它遇到的任何新字符串添加到会话字典中。但是,我只想使用静态字典进行读写,这是事先知道的。
我可以将整个东西包装成 a
GzipStream
并让压缩处理字符串的多个实例。但是,这不会压缩每个字符串的第一个实例,并且总体上看起来像是一个笨拙的解决方法。