为什么Xdocument会给我一个utf16声明?

33

我正在创建一个类似于这样的XDocument:

XDocument doc = new XDocument(
new XDeclaration("1.0", "utf-8", "yes"));

当我用这种方式保存文档(doc.Save(@"c:\tijd\file2.xml");)时,我得到了这个:

<?xml version="1.0" encoding="utf-8" standalone="yes"?>

这是可以的。

但我想要将内容作为 XML 返回,我找到了下面的代码:

 var wr = new StringWriter(); 
            doc.Save(wr); 
            string s = (wr.GetStringBuilder().ToString());

这段代码可以运行,但之后字符串's'以此开头:

<?xml version="1.0" encoding="utf-16" standalone="yes"?>

它从utf8变成了utf16,而这不是我想要的,因为现在我无法在Internet Explorer中阅读它。

有没有一种方法可以防止这种行为发生?


2
这里有一个很大的红旗,字符串编写器确实包含一个utf-16编码的字符串。即使您覆盖了Encoding属性。这个字符串编写器如何传递到IE中? - Hans Passant
好问题。我使用File.WriteAllText将字符串's'保存到文件中,然后用IE打开它。在我的问题中没有太清楚地指明... - Michel
1
对的,File.WriteAllText() 调用是 真正 确定编码的。默认为 utf-8,除非您使用带有 Encoding 的重载。 - Hans Passant
3个回答

43

StringWriter 声称自己使用 UTF-16。不过很容易就可以解决:

public class Utf8StringWriter : StringWriter
{
    public override Encoding Encoding { get { return Encoding.UTF8; } }
}

在你的特定情况下,那应该足够了。一个更全面的实现应该:

  • 具有与 StringWriter 相匹配的构造函数
  • 也允许在构造函数中指定编码方式

1
啊,好的,所以StringWriter会将它变成UTF-16编码。我总是试图理解编码相关的东西,但似乎就是记不住。像StringWriter这样的UTF-16对象创建UTF-16字符串听起来很合理,但让我惊讶的是它还改变了XML文件中的声明。之前在使用XmlDocument而不是XDocument时,我也一直苦恼于UTF-16,所以我认为这只是一个.NET的习惯或者什么的。所以感谢你的回答! - Michel
4
基本上,Save方法会“询问”写入器要使用哪种编码,以便使用适当的编码。我同意这有点混乱... - Jon Skeet
1
我知道这是一个旧的线程,但对于其他使用此解决方案的人,请记住在新建对象时需要使用以下代码:var wr = new Utf8StringWriter(); - SDanks
@SDanks:只需使用TextWriter wr = new Utf8StringWriter();即可。不清楚你想强调什么——这并没有什么特别奇怪的地方。 - Jon Skeet

3
非常好的答案,使用了继承,只需记得覆盖初始化器即可。
   public class Utf8StringWriter : StringWriter
    {
        public Utf8StringWriter(StringBuilder sb) : base (sb)
        {
        }
        public override Encoding Encoding { get { return Encoding.UTF8; } }
    }

1

您需要将 StreamWriter.Encoding 设置为使用 UTF-8 而不是 Unicode (UTF-16)

由于这不是一个 StreamWriter,所以这个答案只留给后人参考。


1
这里没有涉及到StreamWriter。只有一个StringWriter,你无法以编程方式设置它的编码 - 你必须通过继承来实现 :( - Jon Skeet
哇,是的,我完全误读了正在使用的内容。继承就是它。 - msarchet

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接