【问题标题】:Encoding issue. Where am I going wrong?编码问题。我哪里错了?
【发布时间】:2016-09-18 06:04:16
【问题描述】:

我正在尝试从我的服务器传递数据并将其显示在 UWP Windows 应用中。数据存储在 mySQL 数据库中

这是通过 PHP 输出到此处的网页 http://www.rwscripts.com/scorealerts/v3/request.php?action=getTeams 使用此代码

// Serialize the data structure   
    $result = json_encode($data,JSON_PRETTY_PRINT);
    // Display the XML document   
    header('Content-type: application/json; charset=utf-8'); 

    print $result;

然后我在我的应用程序中使用 HttpWebRequest 阅读此内容,然后使用 JSON.net 反序列化 JSON

            JArray obj = JsonConvert.DeserializeObject(str.Trim()) as JArray;
            if (obj == null || obj.Count == 0) return;

            foreach (NotificationTeam nt in from JObject team in obj
                select
                    new NotificationTeam
                    {
                        Title = team.Value<string>("teamName"),
                        TeamID = team.Value<int>("tid"),
                        Followers = team.Value<int>("followers")
                    })
            {
                nt.Notifications = ScoreManager.GetMgr().GetTeamNotification(nt.TeamID);

                notificationTeams.Add(nt);
            }

在我的应用中显示时的输出是这样的

需要更改流程的哪一部分才能正确显示 unicode 字符?

【问题讨论】:

  • 你试过Encoding.ASCII.GetString(yourBytes)
  • 你建议我在哪里使用它?我的网络响应以字符串形式返回 StreamReader requestReader = new StreamReader(response.GetResponseStream()); String webResponse = requestReader.ReadToEnd();
  • 你能把你的实际 Unicode 字符用文本而不是图片发布吗?
  • 在数据库中是 1.FC Köln C# 输出是“1.FC Köln”,json 输出可以在上面的链接中看到
  • 在插入Mysql之前需要用SET NAMES utf8更改服务器连接

标签: c# php mysql json.net uwp


【解决方案1】:

这可能是由于 .NET 连接器中的错误。在这种情况下,您应该指定

character_set_server=utf8mb4

在配置中或[--character-set-server=utf8mb4][1] 在 mysqld 参数中

【讨论】:

    【解决方案2】:

    除了生成的 json 之外,您无法修复此问题 - 因为它完全错误,原因如下:

    • 团队名称 (Köln) 中的特殊字符以 UTF-8 格式存储在您的数据库中。 UTF-8 中的 ö0xc3 0xb6
    • 然后输出数据被编码(或只是格式化)再次为 UTF-16(在 C# 中又称为 Encoding.Unicode) 这是麻烦开始的地方。 UTF-16(和 UTF-32)中的 ö0x00 0xf6
    • UTF-8 字符字节被编码为两个单独的 UTF-16 字符\u00c3\u00b6,而不仅仅是\u00f6。因此,您最终得到的不是 一个 utf-8 字符,而是 两个 utf-16 字符(表示同一个 utf-8 字符的两个字节)。
    • 您的应用识别 \u 转义序列并将它们(完全正确)转换为两个单独的 UTF-16 字符 (ö)。

    长话短说,这就是你的字符串发生的情况:

    ö 在 UTF-32 中是 f6000000
    ö 在 UTF-16 中是 f600
    ö 在 UTF-8 中是 3c b6

    1. Köln(输入)
    2. K[0xc3][0xb6]ln (Sql UTF-8)
    3. K\u00c3\u00b6ln(Json UTF-8 编码为 UTF-16)
    4. Köln(C# UTF-16 解码)

    由于json_encode 需要一个UTF-8 字符串,我怀疑问题发生在数据库和编码(php) 之间的某个地方。

    这篇文章可能会提示您编码设置可能不一致的地方:

    UTF-8-all-the-way-through

    如果您需要修改设置,您需要的输出是:

    "teamName": "1. FC K\u00f6ln""teamName": "1. FC Köln"(应该也可以)

    【讨论】:

      【解决方案3】:

      我相信您需要获取 Unicode 字符的字节并将其转换为 String

      var bytes = Encoding.Unicode.GetBytes(NotificationTeam.Title);
      NotificationTeam.Title = Encoding.ASCII.GetString(bytes);
      

      new NotificationTeam
                          {
                              Title = Encoding.ASCII.GetString(Encoding.Unicode.GetBytes(team.Value<string>("teamName"))),
                              TeamID = team.Value<int>("tid"),
                              Followers = team.Value<int>("followers")
                          })
      

      【讨论】:

      • 执行后者我得到输出 "1\0.\0 \0F\0C\0 \0K\0?\0?\0l\0n\0" 显示为 1. FC K??ln 在应用程序中
      • 你的期望值是多少?
      • 尝试使用dotnetfiddle.net 来创建您的问题;在那里执行下面的代码using System; using System.Text; public class Program { public static void Main() { var unicode = "FC Köln"; Console.WriteLine(Encoding.ASCII.GetString(Encoding.Unicode.GetBytes(unicode))); } }
      • 应该是1.FC Köln
      • 是什么语言?
      【解决方案4】:

      而不是这个..

      $result = json_encode($data,JSON_PRETTY_PRINT);
      

      ..也许这个..?

      $result = json_encode($data,JSON_UNESCAPED_UNICODE);
      

      .. 或两者兼有.. ?

      $result = json_encode($data, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
      

      【讨论】:

      • 我试过这个。它会更改 html 输出,但对应用程序输出没有影响
      • 好吧,我不能再提出任何建议了,因为我没有在 C# 中做任何事情。