c# UNICODE到ANSI的转换

本文关键字:转换 ANSI UNICODE | 更新日期: 2023-09-27 18:17:54

我需要你的帮助有关的东西,这干扰了我工作时与UNICODE编码在。net框架…

我必须与一些非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编码类中没有什么可以帮助用户获得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()函数如何管理这种等价呢?

和有人有一个想法写回ANSI字符从UNICODE文本文件我必须发送给客户?

c# UNICODE到ANSI的转换

我应该……'如果没有找到字符,但没有'S'。为什么?

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

您可以在这里看到cp1252的表,包括Sigma映射。

除了是一个可疑的有用性的无声混乱之外,它还具有一些非常糟糕的安全含义。您应该能够通过将EncoderFallback设置为ReplacementFallbackExceptionFallback来阻止它的发生。

有人有一个想法写回ANSI字符从UNICODE文本文件我必须发送给客户?

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

(为了完整起见,将新客户设置为UTF-8,并说明这是首选编码)