2

我已经编写了我的第一个 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);

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

4

2 回答 2

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 字符集的隐式转换。

我认为这已解决,并感谢每个花时间评论或回答他们的时间和麻烦的人。值得赞赏!

于 2012-10-25T16:04:30.073 回答
1

实际上,您正在正确地进行 Unicode 到 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表来检查这一点。

于 2012-10-23T03:09:38.037 回答