【问题标题】:C# UNICODE to ANSI conversionC# UNICODE 到 ANSI 的转换
【发布时间】:2013-06-10 11:54:44
【问题描述】:

在 .NET Framework 中使用 UNICODE 编码时我需要您的帮助...

我必须与一些非 UNICODE 应用程序的客户数据系统交互,这些客户拥有全球公司(中国、韩国、俄罗斯……)。所以他们必须向我提供一个 ASCII 8 位文件,它将使用他们的 Windows 代码页进行编码。

因此,如果希腊客户向我发送了一个产品名称中包含“Σ”(sigma 字母“\u03A3”)的文本文件,我将得到一个对应于 211 ANSI 代码点的等效字母,以我自己的代码表示页。我的电脑是法语 Windows,这意味着代码页是 Windows-1252,所以我将在这个文本文件中放置“Ó”...好的。

我知道这个客户是希腊人,所以我可以通过在我的导入参数中强制使用 windows-1253 代码页来读取他的文件。

/// <summary>
/// Convert a string ASCII value using code page encoding to Unicode encoding
/// </summary>
/// <param name="value"></param>
/// <returns></returns>
public static string ToUnicode(string value, int codePage)
{
    Encoding windows = Encoding.Default;
    Encoding unicode = Encoding.Unicode;
    Encoding sp = Encoding.GetEncoding(codePage);
    if (sp != null && !String.IsNullOrEmpty(value))
    {
        // First get bytes in windows encoding
        byte[] wbytes = windows.GetBytes(value);

        // Check if CodePage to use is different from current Windows one
        if (windows.CodePage != sp.CodePage)
        {
            // Convert to Unicode using SP code page
            byte[] ubytes = Encoding.Convert(sp, unicode, wbytes);
            return unicode.GetString(ubytes);
        }
        else
        {
            // Directly convert to Unicode using windows code page
            byte[] ubytes = Encoding.Convert(windows, unicode, wbytes);
            return unicode.GetString(ubytes);
        }
    }
    else
    {
        return value;
    }
}

最后我在我的应用程序中得到了“Σ”,我可以将它保存到我的 SQL Server 数据库中。现在我的应用程序必须执行一些复杂的计算,然后我必须通过自动导出将此文件返回给客户......

所以我的问题是我必须执行 UNICODE => ANSI 转换?!但这并不像我一开始想的那么简单……

我不想保存导入时使用的代码页,所以我的第一个想法是将UNICODE转换为windows-1252,然后自动将文件发送给客户。他们将使用自己的代码页读取导出的文本文件,所以这个想法对我来说很有趣。

但问题是这种方式的转换有一个奇怪的行为......这里有两个不同的例子:

第一个例子(я)

char ya = '\u042F';
string strYa = Char.ConvertFromUtf32(ya);
System.Text.Encoding unicode = System.Text.Encoding.Unicode;
System.Text.Encoding ansi1252 = System.Text.Encoding.GetEncoding(1252);
System.Text.Encoding ansi1251 = System.Text.Encoding.GetEncoding(1251);

string strYa1252 = ansi1252.GetString(System.Text.Encoding.Convert(unicode, ansi1252, unicode.GetBytes(strYa)));
string strYa1251 = ansi1251.GetString(System.Text.Encoding.Convert(unicode, ansi1251, unicode.GetBytes(strYa)));

所以 strYa1252 包含 '?',而 strYa1251 包含有效字符 'я'。因此,如果没有将有效的代码页指示给 Convert() 函数,那么似乎不可能转换为 ANSI ... 所以 Unicode Encoding 类中没有任何内容可以帮助用户获得 ANSI 和 UNICODE 代码点之间的等价性? :\

第二个例子(Σ)

char sigma = '\u3A3';
string strSigma = Char.ConvertFromUtf32(sigma);
System.Text.Encoding unicode = System.Text.Encoding.Unicode;
System.Text.Encoding ansi1252 = System.Text.Encoding.GetEncoding(1252);
System.Text.Encoding ansi1253 = System.Text.Encoding.GetEncoding(1253);

string strSigma1252 = ansi1252.GetString(System.Text.Encoding.Convert(unicode, ansi1252, unicode.GetBytes(strSigma)));
string strSigma1253 = ansi1253.GetString(System.Text.Encoding.Convert(unicode, ansi1253, unicode.GetBytes(strSigma)));

此时,我在 strSigma1253 字符串中有正确的 'Σ',但我也有 'S' >strSigma1252。如开头所述,如果找到 ANSI 代码,我应该有 'Ó' 或 '?'如果尚未找到该字符,但不是“S”。为什么? 是的,当然,语言学家可以说“S”等同于希腊语 Sigma 字符,因为它们在两个字母表中听起来相同,但它们的 ANSI 代码不同!

那么 .NET 框架中的 Convert() 函数如何管理这种等价性呢?

是否有人想在我必须发送给客户的文本文件中从 UNICODE 写回 ANSI 字符?

【问题讨论】:

  • 您确实需要知道客户的代码页,然后才能将文本转换回客户的代码页。如果您没有这些信息,您将无法做到这一点。
  • 例如,如果您查看有关 windows-1252 代码页的 MSDN (msdn.microsoft.com/en-us/goglobal/cc305145.aspx),则在此页面底部有一个 ANSI 1252 代码和 UNICODE 代码点之间关系的列表... . 所以我认为从 UNICODE 到一个或多个 ANSI 代码页时存在等价性?示例是fileformat.info/info/unicode/char/3a3/charset_support.htm,其中所有代码都对应于所有 Windows 代码页的 sigma ...
  • 让您的客户自己使用 UTF-8 或 Unicode 工作可能会更好。你也控制他们使用的软件吗?
  • 完全不是,这是问题所在:P 我们只提供与我们的应用程序和他们的应用程序的接口,这些接口通常是一些旧的“自制”(和非 UNICODE 等)工业软件......我猜如果解决方案是将客户迁移到某些工业 UTF8 应用程序,我不会发布这个问题 ^^ 我真的需要通过返回 ASCII 8bits 文件来确保与他们的系统的兼容性......
  • 没有 8 位 ASCII 这样的东西。所以你必须知道要保存到哪个代码页。

标签: c# unicode ansi


【解决方案1】:

我应该...'?'如果未找到该字符,但未找到“S”。为什么?

这被称为“最佳匹配”编码,在大多数情况下这是一件坏事。当 Windows 无法将字符编码到目标代码页时(因为代码页 1252 中不存在 Σ),它会尽最大努力将字符映射到有点像它的东西。这可能意味着丢失变音符号(ëe),或映射到同源(ΣS),一个相关的字符(=),一个不相关的字符但看起来有点相似(8),或者任何其他疯狂的替换在当时似乎是个好主意,但在实践中被证明在文化或数学上令人反感。

您可以查看 cp1252 的表格,包括那个 Sigma 映射,here

除了是对可疑用途的无声修改之外,它还有一些quite bad security implications。您应该能够通过将EncoderFallback 设置为ReplacementFallbackExceptionFallback 来阻止它发生。

有人想在我必须发送给客户的文本文件中从 UNICODE 写回 ANSI 字符吗?

您必须为每个客户保留一个编码表。使用该编码读取他们的输入文件进行解码;使用相同的编码写入他们的输出文件。

(为了理智,将新客户设置为 UTF-8 并记录这是首选编码。)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-04-20
    • 2013-08-21
    • 1970-01-01
    • 1970-01-01
    • 2017-11-29
    • 2011-06-03
    • 1970-01-01
    相关资源
    最近更新 更多