如何防止Windows-1252参数转换为Unicode字符串?

时间:2012-10-23 00:10:08

标签: c# com

我写过我的第一个COM课程。我的单元测试工作正常,但我第一次使用COM对象遇到了麻烦。

COM类提供接受字符串,操作它并返回字符串的方法。 COM对象的使用者是dBASE PLUS程序。

当输入字符串包含常用键盘字符(ASCII 127或更低)时,COM方法可以正常工作。但是,如果字符串包含超出ASCII范围的字符,则其中一些字符串会从Windows-1252重新映射到C#的Unicode。此表显示了发生的映射:http://www.unicode.org/Public/MAPPINGS/VENDORS/MICSFT/WINDOWS/CP1252.TXT

例如,如果dBASE程序使用:

调用COM对象

oMyComObject.MyMethod("It will cost123")其中€为十六进制80,

C#方法将其作为Unicode接收:

public string MyMethod(string source)
{
    // source is Unicode and now the Euro symbol is hex 20AC
    ...
}

我想避免重新映射,因为我想要字符串的原始十六进制内容。

我尝试将以下内容添加到MyMethod以将字符串转换回Windows-1252,但欧元符号会丢失,因为它会成为问号:

        byte[] UnicodeBytes = Encoding.Unicode.GetBytes(source.ToString());
        byte[] Win1252Bytes = Encoding.Convert(Encoding.Unicode, Encoding.GetEncoding(1252), UnicodeBytes);
        string Win1252 = Encoding.GetEncoding(1252).GetString(Win1252Bytes);

有没有办法阻止“source”参数转换为Unicode?或者,有没有办法将它100%从Unicode转换回Windows-1252?

2 个答案:

答案 0 :(得分:2)

是的,我正在回答我自己的问题。 “Jigsore”的回答让我走上正轨,但我想更清楚地解释一下,如果其他人犯了同样的错误。

我最终发现我误解了这个问题。 dBASE正在传递字符串,C#接收它很好。这是我检查错误字符串内容的方式。

这个交钥匙建立在Jigsore的答案之上:

void Main()
{
    string unicodeText = "\u20AC\u0160\u0152\u0161";

    byte[] unicodeBytes = Encoding.Unicode.GetBytes(unicodeText);
    byte[] win1252bytes = Encoding.Convert(Encoding.Unicode, Encoding.GetEncoding(1252), unicodeBytes);
    for (int i = 0; i < win1252bytes.Length; i++)
        Console.Write("0x{0:X2} ", win1252bytes[i]); // output: 0x80 0x8A 0x8C 0x9A

    // win1252String represents the string passed from dBASE to C#
    string win1252String = Encoding.GetEncoding(1252).GetString(win1252bytes);

    Console.WriteLine("\r\nWin1252 string is " + win1252String); // output: Win1252 string is €ŠŒš
    Console.WriteLine("looking at the code of the first character the wrong way: " + (int)win1252String[0]);
    // output: looking at the code of the first character the wrong way: 8364

    byte[] bytes = Encoding.GetEncoding(1252).GetBytes(win1252String[0].ToString());

    Console.WriteLine("looking at the code of the first character the right way: " + bytes[0]);
    // output: looking at the code of the first character the right way: 128

    // Warning: If your input contains character codes which are large in value than what a byte
    // can hold (ex: multi-byte Chinese characters), then you will need to look at more than just bytes[0].
}

第一种方法错误的原因是,转换(int)win1252String[0](或者将整数j转换为带有(char)j的字符的相反方法)涉及使用C#使用的Unicode字符集进行隐式转换。 / p>

我认为这已经解决了,并且要感谢每个花时间评论或回答他们的时间和麻烦的人。非常感谢!

答案 1 :(得分:1)

实际上你正在进行Unicode to Win-1252转换,但是你正在执行额外的步骤。原始的Win1252代码位于 Win1252Bytes 数组中! 请检查以下代码:

string unicodeText = "\u20AC\u0160\u0152\u0161";

byte[] unicodeBytes = Encoding.Unicode.GetBytes(unicodeText);
byte[] win1252bytes = Encoding.Convert(Encoding.Unicode, Encoding.GetEncoding(1252), unicodeBytes);
for (i = 0; i < win1252bytes.Length; i++)
    Console.Write("0x{0:X2} ", win1252bytes[i]);

输出显示 unicodeText 字符串的 Win-1252 代码,您可以通过查看 CP1252.TXT 表进行检查。