为什么我的ATOM XML是UTF-16而不是UTF-8

时间:2022-06-05 20:16:38

I have this code to create an ATOM feed

我有这个代码来创建一个ATOM提要

Dim xmlResult As New StringBuilder
Dim settings As New XmlWriterSettings
Dim atomWriter As XmlWriter = XmlWriter.Create(xmlResult, settings)
Dim atomFormatter As Atom10FeedFormatter = New Atom10FeedFormatter(feed)
atomFormatter.WriteTo(atomWriter)
atomWriter.Close()

It returns XML that starts like this:

它返回如下所示的XML:

<?xml version="1.0" encoding="utf-16"?><feed xmlns="http://www.w3.org/2005/Atom">

No matter what I try I can't get it to return utf-8 instead of utf-16. When it is utf-16 it fails to work with IE8 but utf-8 works OK. How do I know it works OK I hear you ask if I can't get it to return utf-8, well I end up using this line of code to return the feed to the browser:

无论我尝试什么,我都无法让它返回utf-8而不是utf-16。当它是utf-16时它无法使用IE8但是utf-8工作正常。我怎么知道它工作正常我听到你问我是不是让它返回utf-8,我最终使用这行代码将源返回到浏览器:

Response.Write(Replace(xmlResult.ToString, "utf-16", "utf-8"))

Which is surely the worst hack you've seen today, if it isn't I feel sorry for you!

这肯定是你今天看到的最糟糕的黑客,如果不是我为你感到难过!

So this is what I have tried to get UTF-8:

所以这就是我试图获得的UTF-8:

Response.ContentEncoding = System.Text.Encoding.UTF8
Response.Charset = "UTF-8"
settings.Encoding = System.Text.Encoding.UTF8

The settings line is what I thought would work but isn't for me. My understanding is that the XML Writer is the part that is adding the XML declaration but as the settings.Encoding doesn't work I'm stumped. Please help!

设置行是我认为可行但不适合我的。我的理解是XML Writer是添加XML声明的部分,但作为settings.Encoding不起作用我很难过。请帮忙!

Thanks

2 个解决方案

#1


The underlying reason is that when you call XmlWriter.Create with a StringBuilder, it creates a new StringWriter instance, which always has an encoding of UTF-16, and creates an XmlWriter around that StringWriter. Looking in Reflector, it looks like the encoding of StringWriter is a private, static variable, so all StringWriter instances will have the same encoding.

根本原因是,当您使用StringBuilder调用XmlWriter.Create时,它会创建一个新的StringWriter实例,该实例的编码始终为UTF-16,并在该StringWriter周围创建一个XmlWriter。查看Reflector,看起来StringWriter的编码是一个私有的静态变量,因此所有StringWriter实例都具有相同的编码。

Is there some reason you're not creating an XmlWriter that directly writes to the Response OutputStream?

是否有一些原因你没有创建直接写入Response OutputStream的XmlWriter?

If you can do that, this code works for me:

如果你能做到这一点,这段代码对我有用:

With Response
  .ContentEncoding = Encoding.UTF8
  .ContentType = "text/xml"
End With

Dim atomFormatter As Atom10FeedFormatter = New Atom10FeedFormatter(feed)
Dim settings As XmlWriterSettings = New XmlWriterSettings

With settings
  .OmitXmlDeclaration = False
  .Encoding = Encoding.UTF8
End With

Using atomWriter As XmlWriter = XmlWriter.Create(Response.OutputStream, settings)
  atomFormatter.WriteTo(atomWriter)
  atomWriter.Close()
End Using

Response.End()

If you must use StringBuilder for a good reason, perhaps you might consider omitting the Xml Declaration and adding it in your code before the atomFormatter.WriteTo call. Alternatively, you could write your function to accept an arbitrary Stream and create an XmlWriter on that, using a MemoryStream or FileStream when you aren't planning to write directly to the Response.OutputStream.

如果你有充分的理由必须使用StringBuilder,也许你可以考虑省略Xml声明并在atomFormatter.WriteTo调用之前将它添加到你的代码中。或者,当您不打算直接写入Response.OutputStream时,您可以使用MemoryStream或FileStream编写函数以接受任意Stream并在其上创建XmlWriter。

Apologies if the code is not idiomatic VB; I mostly write in C#.

如果代码不是惯用VB,请道歉;我主要用C#写。

#2


Try "settings.Encoding = System.Text.Encoding.UTF8"

试试“settings.Encoding = System.Text.Encoding.UTF8”

I have tried it and, as MrBrutal noticed, it does not work.

我已经尝试过了,正如布鲁塔尔先生所注意到的,它不起作用。

My guess it that because the string in .NET is always UTF-16, writing an XML into a string will always force the encoding to utf-16, no matter what.

我的猜测是因为.NET中的字符串总是UTF-16,所以将XML写入字符串将始终强制编码为utf-16,无论如何。

You should try writing to a stream, where you have more control. If the goal is to write into a file, then the stream should be connected to that and write directly there.

你应该尝试写一个流,你有更多的控制权。如果目标是写入文件,则应将流连接到该文件并直接在那里写入。

If writing to a file is not the ultimate goal, then what is is? Might help a bit if you explain a bit the use case. Maybe the final result belongs in a byte array, not a string.

如果写入文件不是最终目标,那么它是什么?如果你解释一下用例,可能会有所帮助。也许最终结果属于字节数组,而不是字符串。

#1


The underlying reason is that when you call XmlWriter.Create with a StringBuilder, it creates a new StringWriter instance, which always has an encoding of UTF-16, and creates an XmlWriter around that StringWriter. Looking in Reflector, it looks like the encoding of StringWriter is a private, static variable, so all StringWriter instances will have the same encoding.

根本原因是,当您使用StringBuilder调用XmlWriter.Create时,它会创建一个新的StringWriter实例,该实例的编码始终为UTF-16,并在该StringWriter周围创建一个XmlWriter。查看Reflector,看起来StringWriter的编码是一个私有的静态变量,因此所有StringWriter实例都具有相同的编码。

Is there some reason you're not creating an XmlWriter that directly writes to the Response OutputStream?

是否有一些原因你没有创建直接写入Response OutputStream的XmlWriter?

If you can do that, this code works for me:

如果你能做到这一点,这段代码对我有用:

With Response
  .ContentEncoding = Encoding.UTF8
  .ContentType = "text/xml"
End With

Dim atomFormatter As Atom10FeedFormatter = New Atom10FeedFormatter(feed)
Dim settings As XmlWriterSettings = New XmlWriterSettings

With settings
  .OmitXmlDeclaration = False
  .Encoding = Encoding.UTF8
End With

Using atomWriter As XmlWriter = XmlWriter.Create(Response.OutputStream, settings)
  atomFormatter.WriteTo(atomWriter)
  atomWriter.Close()
End Using

Response.End()

If you must use StringBuilder for a good reason, perhaps you might consider omitting the Xml Declaration and adding it in your code before the atomFormatter.WriteTo call. Alternatively, you could write your function to accept an arbitrary Stream and create an XmlWriter on that, using a MemoryStream or FileStream when you aren't planning to write directly to the Response.OutputStream.

如果你有充分的理由必须使用StringBuilder,也许你可以考虑省略Xml声明并在atomFormatter.WriteTo调用之前将它添加到你的代码中。或者,当您不打算直接写入Response.OutputStream时,您可以使用MemoryStream或FileStream编写函数以接受任意Stream并在其上创建XmlWriter。

Apologies if the code is not idiomatic VB; I mostly write in C#.

如果代码不是惯用VB,请道歉;我主要用C#写。

#2


Try "settings.Encoding = System.Text.Encoding.UTF8"

试试“settings.Encoding = System.Text.Encoding.UTF8”

I have tried it and, as MrBrutal noticed, it does not work.

我已经尝试过了,正如布鲁塔尔先生所注意到的,它不起作用。

My guess it that because the string in .NET is always UTF-16, writing an XML into a string will always force the encoding to utf-16, no matter what.

我的猜测是因为.NET中的字符串总是UTF-16,所以将XML写入字符串将始终强制编码为utf-16,无论如何。

You should try writing to a stream, where you have more control. If the goal is to write into a file, then the stream should be connected to that and write directly there.

你应该尝试写一个流,你有更多的控制权。如果目标是写入文件,则应将流连接到该文件并直接在那里写入。

If writing to a file is not the ultimate goal, then what is is? Might help a bit if you explain a bit the use case. Maybe the final result belongs in a byte array, not a string.

如果写入文件不是最终目标,那么它是什么?如果你解释一下用例,可能会有所帮助。也许最终结果属于字节数组,而不是字符串。