将对象序列化为字符串:为什么我的编码添加了愚蠢的字符

本文关键字:添加 字符 编码 我的 序列化 对象 字符串 为什么 | 更新日期: 2023-09-27 18:04:15

我需要以字符串的形式获得对象的序列化XML表示。我使用XmlSerializer和memoryStream来做到这一点。

XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
using (MemoryStream stream = new MemoryStream())
{
  using (XmlTextWriter writer = new XmlTextWriter(stream,Encoding.UTF8))
  {
    serializer.Serialize(writer, myClass);
    string xml = Encoding.UTF8.GetString(stream.ToArray());
    //other chars may be added from the encoding.
    xml = xml.Substring(xml.IndexOf(Convert.ToChar(60)));
    xml = xml.Substring(0, (xml.LastIndexOf(Convert.ToChar(62)) + 1));
    return xml;
  }
}

现在只需注意xml。子字符串行一会儿。我发现的是(即使我在xmltextwwriter和GetString上指定编码(我使用memoryStream.ToArray(),所以我只对流缓冲区中的数据进行操作)…生成的XML字符串添加了一些非XML快乐字符。对我来说,a '?'在字符串的开头。这就是为什么我要为'<'和'>'添加子字符串,以确保我只得到好的东西。

奇怪的是,在调试器(文本可视化器)中查看这个字符串,我没有看到这个'?'。只有当我将可视化工具中的内容粘贴到记事本或类似的地方时。

那么,当上面的代码(子字符串等)完成工作时,这里实际发生了什么?是否包含一些无符号字节的东西,而不是在文本可视化器中表示?

将对象序列化为字符串:为什么我的编码添加了愚蠢的字符

您可以通过具体指定编码来排除BOM -即,而不是Encoding.UTF8,尝试使用:

using (MemoryStream stream = new MemoryStream())
{
  var enc = new UTF8Encoding(false);
  using (XmlTextWriter writer = new XmlTextWriter(stream,enc))
  {
    serializer.Serialize(writer, myClass);        
  }
  string xml = Encoding.UTF8.GetString(
      stream.GetBuffer(), 0, (int)stream.Length);
}

您正在查看的是字节顺序标记(BOM)。这在UTF8中是正常的!

简而言之,对于我的评论爱好者来说:它们是字节标记,决定字符串的端序。

你可以做的是使用a) ASCII作为你的编码,这将删除字节顺序标记…或者b)为什么不把它们留在里面?它们确实为xml字符串提供了一个有用的功能。

Marc Gravell给出了第三种选择:创建自己的编码对象,并在构造函数中指定false以抑制字节顺序标记。