【问题标题】:UTF-8 to C# string from a DataReader来自 DataReader 的 UTF-8 到 C# 字符串
【发布时间】:2012-03-11 23:59:19
【问题描述】:

我有一个返回 UTF-8 编码字段(varchar)的 MS SQL 查询。如何将其转换为 .NET Unicode 字符串? UTF8Encoding.GetString 将完成这项工作......如果你有一个字节数组 - 我没有。

【问题讨论】:

  • 如果你没有字节数组,那你有什么?如果它是一个字符串,那么它可能已经被您的数据库或 ADO.NET 提供程序解码。
  • 你有什么?我认为您不需要将 SQL 字符串转换为 .NET 字符串。
  • 它是一个 varchar ...所以就数据读取器而言,它是一个字符串
  • @Rob 所以应该以字符串的形式呈现给你的 C# 代码。为什么你不能只使用那个字符串?有具体问题吗?
  • 是的,它是一个字符串 - 即转换为 Unicode 的 ANSI 字符串。它不是。它是一个 UTF-8 字符串,我需要在转换之前得到它。

标签: c# sql-server unicode utf-8


【解决方案1】:

好的起点:http://msdn.microsoft.com/en-us/library/kdcak6ye.aspx 要获取原始字符串的字节,您可以使用System.Text.Encoding.UTF8.GetBytes() 方法。

【讨论】:

  • 嗯...您建议将字符串编码回字节数组,然后再次将其解码回字符串(甚至在中间通过Encoding.Convert 将其从字节数组转码为字节数组)所有这些)?这样做有什么可能的目的?
  • 我尝试从字符串中取出每个字符并使用它来设置一个字节数组。这不起作用,因为高位字符已经映射到它们的 Unicode 等价物。
  • @Rob 为什么你尝试这样做?为什么不能按原样使用字符串?您是否有没有告诉我们的具体问题?
  • 因为字符串'as-is'不是数据库中的那个,所以已经转换了。例如(我正在编数字),汉字的 UTF8 编码可能是 0x80 0x99 0x14。但是,当 ADO.NET(或 CLR)看到这三个字符时,它会自动将它们转换为它们的 Unicode 表示形式。 0x99,TM ​​符号的 Windows 字符被转换为 Unicode 0x8482。我无法将它传递给 UTF 解码器。
【解决方案2】:

我改编了从the MSDN forums 学到的东西。查询返回带有 UTF-8 编码文本的 varchardatetimeint 值。我正在根据结果构建一个 CSV 文件。

using (var sw = new StreamWriter(txtOutputFile, true, Encoding.UTF8))
{
  while (r.Read())
  {
    var colCount = r.FieldCount;
    var curCol = 1;

    var utf8 = new UTF8Encoding();
    var row = "";

    if (r[0].GetType() == typeof(SqlString))
    {
      SqlString sqlString = r.GetSqlString(0);
      Byte[] encodedBytes = sqlString.GetNonUnicodeBytes();
      row = "\"" + utf8.GetString(encodedBytes) + "\"";
    }
    else
    {
      row = "\"" + r[0].ToString() + "\"";
    }

    while (curCol < colCount)
    {
      if (r[curCol].GetType() == typeof(SqlString))
      {
        SqlString sqlString = r.GetSqlString(curCol);
        Byte[] encodedBytes = sqlString.GetNonUnicodeBytes();
        row += ",\"" + utf8.GetString(encodedBytes) + "\"";
      }
      else
      {
        row += ",\"" + r[curCol].ToString() + "\"";
      }
      curCol += 1;
    }

    sw.WriteLine(row);
  }

}

【讨论】:

    【解决方案3】:

    如果您有一个 C# string,其内容被错误地解释为 UTF-16 编码,那么您可以重新解释底层字节:

    public static string InterpretAsUTF8(string value)
    {
      byte[] rawData = Encoding.Default.GetBytes(value);
      string reencoded = Encoding.UTF8.GetString(rawData);
      return reencoded;
    }
    

    但是,如果您可以访问SqlDataReader,那么按照@CarlSteffen 的建议,您可以这样做:

    //Assuming the column index you're interested in is 1:
    SqlString utf8EncodedString = reader.GetSqlString(1);
    string expectedResult = Encoding.UTF8.GetString(utf8EncodedString.GetNonUnicodeBytes());
    

    【讨论】:

      【解决方案4】:

      根据这个问题改编了一个可能的解决方案:C# Convert string from UTF-8 to ISO-8859-1 (Latin1) H

      var dbEnc = Encoding.UTF8;
      var uniEnc = Encoding.Unicode;
      byte[] dbBytes = dbEnc.GetBytes(dbString);
      byte[] uniBytes = Encoding.Convert(dbEnc, uniEnc, dbBytes);
      string msg = uniEnc.GetString(uniBytes);
      

      这有帮助吗?

      【讨论】:

      • 我认为问题在于从提供者那里获取的字符串已经被弄乱了。
      • 嗯。使用 DbDataReader.GetBytes(...) 将数据读入字节数组怎么样?另外,您是否可以控制进入数据库的内容?使用更多细节和上下文更新您的问题可能值得,例如示例数据库数据、当前代码的当前输出以及您想要实现的最终结果。
      • 我会在我回到办公室时试一试。
      • 看来它根本无法用 varchar 字段完成。真是太神奇了。但是,可以使用 TEXT 字段来完成,并且只需转换就足够了(即 cast(description as text) as description )。一旦是 TEXT,DbDataReader 就可以获取原始字符串。
      • 有趣。提醒一下,TEXT/NTEXT 在 SQL Server 的未来版本中将被弃用:msdn.microsoft.com/en-us/library/ms187993.aspx 我倾向于使用 nvarchar 而不是 varchar,这样做会更好吗?
      猜你喜欢
      • 2017-03-04
      • 2023-03-27
      • 2016-05-31
      • 1970-01-01
      • 2012-01-20
      • 2017-07-02
      • 2019-04-28
      • 2019-08-08
      • 2011-08-16
      相关资源
      最近更新 更多