【问题标题】:Why does this UTF-16 HTTP response end up as UTF-8 when in the resulting Stream?为什么这个 UTF-16 HTTP 响应在结果流中以 UTF-8 结尾?
【发布时间】:2020-11-13 02:05:22
【问题描述】:

我遇到了一个服务向我返回 HTTP 标头的问题:

Content-Type: application/json; charset=utf-16

当它被 C# 序列化时,它会以 UTF-8 流结束,这显然会中断。似乎 utf-16 是IANA spec 中的有效编码。那么为什么这段代码不起作用呢?

System.Net.Http.HttpClient httpClient ...;
using (var response = await httpClient.SendAsync(request, HttpCompletionOption.ResponseHeadersRead))
{
   //response.Content.Headers.ContentType.CharSet = "utf-16"
   using (var responseContentStream = await response.Content.ReadAsStreamAsync())
   {
       using (var streamReader = new StreamReader(stream))
       {
          //streamReader.CurrentEncoding.BodyName returns utf-8 here?! 
       }
   }
} 

所以最初response 看起来不错,但一旦它到达streamReader,它似乎恢复为utf-8。为什么?

【问题讨论】:

  • 您似乎期望 StreamReader(将单个字节转换为字符串)仅从流中确定编码。
  • 如果内容足够小,请使用response.Content.ReadAsStringAsync()——它具有使用正确编码的聪明才智。如果你使用StreamReader,你只是给它一个Stream,没有关于使用编码的信息
  • 当客户端和服务器连接时发生协商,服务器上的网页标头和请求中的标头用于确定常见的操作模式。在某些情况下,服务器会忽略客户端标头,而在其他情况下,服务器将支持客户端标头中的模式。例如,服务器可能同时支持英语和法语。因此,服务器使用来自客户端的标头来确定使用正确语言的主页。每个服务器都是不同的。您是否在请求中包含了字符集。在某些情况下,语言决定了编码。
  • HttpContent 在使用ReadAsStringAsync() 时使用this logic 来确定响应的编码。如果你使用ReadAsStreamAsync(),那么当然不会运行任何代码。
  • @Liam 流只是字节的集合,仅此而已。没有编码的概念,因为任何旧的任意流都可能不代表文本!

标签: c# encoding http-headers content-type asp.net-core-3.1


【解决方案1】:

您可以在构造函数中指定 StreamReader 应使用的编码。 在您的情况下,它应该如下所示:

using (var streamReader = new StreamReader(stream, Encoding.Unicode, true))
{
  // The reader should read the Stream with UTF-16 here
}

【讨论】:

  • 这不是我真正想要的,这可能会返回 utf-8 或 utf-16。我想知道的是为什么 StreamReader 不尊重 HTTP 响应中的编码
  • @Liam 因为 StreamReader 对 HTTP 响应一无所知。你什么都没说!你给它的只是一个字节的集合
  • @Liam 如果未指定其他编码,则 StreamReader 默认使用 UTF-8。但是您可以从响应标头中读取编码并相应地切换阅读器编码
猜你喜欢
  • 2017-09-18
  • 2012-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-09-21
相关资源
最近更新 更多