我写过我的第一个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 cost
€123")
其中€为十六进制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?
答案 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 表进行检查。