【问题标题】:XmlSerializer.Serialize BOM missingXmlSerializer.Serialize BOM 丢失
【发布时间】:2019-07-04 09:15:28
【问题描述】:

我正在使用此代码来存储我的课程:

FileStream stream = new FileStream(myPath, FileMode.Create);
XmlSerializer serializer = new XmlSerializer(typeof(myClass));
serializer.Serialize(stream, myClass);
stream.Close();

这会写入一个我可以使用XmlSerializer.Deserialize 正常读取的文件。但是,生成的文件不是正确的文本文件。 XmlSerializer.Serialize 不存储 BOM,但仍插入多字节字符。因此它被隐式声明为 ANSI 文件(因为我们期望 XML 文件是文本文件,而没有 BOM 的文本文件被 Windows 视为 ANSI),在某些编辑器中将 ö 显示为 ö。

这是一个已知的错误吗?还是我缺少的一些设置?

生成的文件开头如下:

<?xml version="1.0"?>
<SvnProjects xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">

文件中的第一个字节是十六进制 3C,即&lt;

【问题讨论】:

标签: c# xmlserializer


【解决方案1】:

拥有或不拥有 BOM 并不是“正确的文本文件”的定义。事实上,我想说现在最典型的格式是没有 BOM 的 UTF-8;我认为我曾经见过有人在实际系统中实际使用 UTF-8 BOM!但是:如果你想要一个 BOM,那很好:只需传递正确的 Encoding 即可;如果你想要带有 BOM 的 UTF-8:

using (var writer = XmlWriter.Create(myPath, s_settings))
{
    XmlSerializer serializer = new XmlSerializer(typeof(MyClass));
    serializer.Serialize(writer, obj);
}

与:

static readonly XmlWriterSettings s_settings =
    new XmlWriterSettings { Encoding = new UTF8Encoding(true) };

这样做的结果是一个以 EF-BB-BF 开头的文件,即 UTF-8 BOM。

如果您想要不同的编码,只需将new UTF8Encoding 替换为您想要的任何内容,记住启用 BOM。

(注意:静态 Encoding.UTF8 实例启用了 BOM,但如果您特别打算使用 BOM,IMO 最好在此处非常明确,就像您应该非常明确 Encoding 您的意图一样使用)


编辑:这里的主要区别在于 Serialize(Stream, object) 最终使用:

XmlTextWriter xmlWriter = new XmlTextWriter(stream, encoding: null) {
    Formatting = Formatting.Indented,
    Indentation = 2
};

然后最终使用:

public StreamWriter(Stream stream) : this(stream,
    encoding: UTF8NoBOM, // <==== THIS IS THE PROBLEM
    bufferSize: 1024, leaveOpen: false)
{
}

所以:如果您使用该 API,则默认为不带 BOM 的 UTF-8。

【讨论】:

  • 非常感谢您的解决方案和详尽的解释。
【解决方案2】:
  1. 您必须 xml 一个 实例 而不是类定义
  2. 要获得 Unicode,您必须声明 XmlWriter 或 TextWriter
FileStream stream = new FileStream(myPath, FileMode.Create);
XmlSerializer serializer = new XmlSerializer(typeof(myClass));
XmlWriter writer = new XmlTextWriter(fs, Encoding.Unicode);
serializer.Serialize(writer, myClass);
stream.Close();

【讨论】:

  • 好的,谢谢。这是主要问题。我怀疑 XmlWriter 编写了一个正确的文本文件,因为 XML 是文本。但是 XmlWriter 依赖于底层流/编写器来正确写入文本,因此必须使用显式文本编写器。我保持接受 Marc Gravell 的答案,因为他展示了幕后发生的事情,而我只能接受一个答案。无论如何 +1。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-02
  • 1970-01-01
  • 2010-09-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多