2

私は最初のCOMクラスを作成しました。私の単体テストは正常に機能しますが、COMオブジェクトの最初の使用で問題が発生しました。

COMクラスは、文字列を受け取り、それを操作して文字列を返すメソッドを提供します。COMオブジェクトのコンシューマーは、dBASEPLUSプログラムです。

入力文字列に一般的なキーボード文字(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")ここで、€は16進数の80であり、

C#メソッドはそれをUnicodeとして受け取ります:

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

文字列の元の16進コンテンツが必要なため、この再マッピングは避けたいと思います。

次の文字列を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からWindows-1252に100%変換する方法はありますか?

4

2 に答える 2

2

はい、私は自分の質問に答えています。「ジグソール」の答えは正しい方向に進んでいますが、他の誰かが私と同じ過ちを犯した場合に備えて、より明確に説明したいと思います。

結局、私は問題を誤診したことに気づきました。dBASEは文字列を正常に渡し、C#はそれを正常に受信していました。エラーが発生したのは、文字列の内容を確認する方法でした。

このターンキーは、ジグソールの答えに基づいています。

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 に答える