C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: UTF-8 <> Shift_JISの文字コード変換について


(過去ログ 71 を表示中)

[トピック内 3 記事 (1 - 3 表示)]  << 0 >>

■41702 / inTopicNo.1)  UTF-8 <> Shift_JISの文字コード変換について
  
□投稿者/ jose (1回)-(2009/09/28(Mon) 19:17:24)

分類:[C#] 

2009/09/28(Mon) 20:20:51 編集(投稿者)
2009/09/28(Mon) 20:20:18 編集(投稿者)
2009/09/28(Mon) 20:20:08 編集(投稿者)

いつも参考にさせていただいています。joseと申します。

UTF-8からShift_JISへの変換、およびその逆を行おうとしています。
下記のコードにて、結果としてtrueが返って来る事を期待していますが、
originalStringのバイト配列表現は{227, 129, 130}
utf8EncodedStringのバイト配列表現は{227, 129, 129, 69}
となり、一致せず、falseが返ってきます。

一致することを期待しているのですが、どうしてこのようになるのでしょうか。
環境はC# 2.0です。

class Program
{
    public const string encodeString = "shift_jis";

    static void Main(string[] args)
    {
        string originalString = "あ";

        string sjisEncodedString = 
            ConvertEncoding(
                originalString, 
                Encoding.UTF8, 
                Encoding.GetEncoding(encodeString));

        string utf8EncodedString = 
            ConvertEncoding(
                sjisEncodedString, 
                Encoding.GetEncoding(encodeString), 
                Encoding.UTF8);

        Console.WriteLine(string.Equals(originalString, utf8EncodedString)); // trueを期待
    }

    public static string ConvertEncoding(string src, System.Text.Encoding srcEncoding, System.Text.Encoding destEncoding)
    {
        byte[] bytesData = srcEncoding.GetBytes(src);

        return destEncoding.GetString(bytesData);
    }
}

引用返信 編集キー/
■41703 / inTopicNo.2)  Re[1]: UTF-8 <> Shift_JISの文字コード変換について
□投稿者/ 魔界の仮面弁士 (1326回)-(2009/09/28(Mon) 20:29:07)
2009/09/28(Mon) 20:35:54 編集(投稿者)
No41702 (jose さん) に返信
> UTF-8からShift_JISへの変換、およびその逆を行おうとしています。

コードの意図が良く読み取れないのですが、
これらは、何を目的としたコードなのでしょうか?

UTF-8 エンコードのバイナリを、無理に Shift_JIS 文字列にデコードしても、
それは意味を持ちません。文字データを破損させてしまうだけです。


> 一致することを期待しているのですが、
そもそも無理があります。

例えば、「中国語→日本語」変換アプリに、(中国語ではなく)日本語を
翻訳させたら、その結果は出鱈目な物になる事は想像が付きますよね。
http://www.excite.co.jp/world/chinese/

中国語では無い文章を、中国語として解釈しようとすれば破損してしまうのと同様、
Shift_JIS ではありえないバイナリデータを Shift_JIS 文字列として解釈させようとしても、
それはそもそも無理という物です。


> originalStringのバイト配列表現は{227, 129, 130}
これは、UTF-8 としてみた場合のバイナリ表現、ですね?
(16進数表記で言えば、E3 81 82 ですね)

> utf8EncodedStringのバイト配列表現は{227, 129, 129, 69}
こちらも、UTF-8 としてみた場合のバイナリ表現ですね?
(16進数表記で言えば、E3 81 81 45)



> どうしてこのようになるのでしょうか。
「あ」という文字を、Shift_JIS / UTF-8 でエンコードすると、
  82 A0    : Shift_JIS
  E3 81 82 : UTF-8
となります。ここまでは大丈夫でしょうか。


最初に、ConvertEncoding("あ", UTF8, Shift_JIS) の処理から説明しますが、ここでは
 (1) "あ" を、UTF-8 バイナリの E3 81 82 に変換する。
 (2) E3 81 82 を Shift_JIS 文字列に逆変換する。
という手順が行われています。そして、この手順 2 の Shift_JIS 化が破損の原因です。

最初の 2 バイト(E3 81)については、Shift_JIS では "縺" の文字を意味するので良いのですが、
その後の 82 という値が問題です。82 は Shift_JIS では 2バイト文字の先導バイトを意味しており、
これ単体では文字たりえません。このあとに少なくとも 1バイト (40〜7E、80〜FCの範囲)が必要です。

結果として、このバイナリは "縺" + {破損文字} な文字列として解釈される事になりますが、
無理に文字列化せねばならなかったため、今回は恐らく、その破損文字が "・" という
代替文字(Shift_JIS = 81 45、UTF-8 = E3 83 BB) にて代用されたのでしょう。


さて、次は ConvertEncoding("縺・", Shift_JIS, UTF8) の処理についてです。こちらは、
 (1) "縺・" を、Shift_JIS バイナリの E3 81 81 45 に変換する。
 (2) E3 81 81 45 を UTF-8 文字列に逆変換する。(つまり、"ぁE" という文字列になる)
という手順が行われる事になります。

こちらは運よく、先ほどのような破損文字が生成される事はありませんでしたが、
そもそも入力データが既に破損しているので、残念ながら手順 1 自体が意味を持ちません。

こうして、"あ" が "ぁE" へと化ける事になったわけです。


中には、元通りに復元できる文字列もありますが、それはたまたま、文字データが
破損しないようなバイナリの組み合わせが得られただけとみるべきでしょうね。

引用返信 編集キー/
■41705 / inTopicNo.3)  Re[2]: UTF-8 <> Shift_JISの文字コード変換について
□投稿者/ jose (2回)-(2009/09/28(Mon) 21:44:09)
No41703 (魔界の仮面弁士 さん) に返信
> 2009/09/28(Mon) 20:35:54 編集(投稿者)
>
丁寧で素早い回答ありがとうございました。

大きな勘違いを2つしておりました。

1. 以下のコードでUTF-8バイナリをShift_JIS文字列として返却するものと思っておりました。
byte[] bytesData = Encoding.UTF8.GetBytes(src);
return Encoding.GetEncoding("Shift_JIS").GetString(bytesData);

これはおっしゃる通り、UTF-8バイナリをShift_JISバイナリとみなして
操作をしてしまっておりますので、全く意味がないものと理解しました。

2. そもそもstring型にはUnicode文字列が格納されるのであり、Shift_JISなどの他の
文字エンコードの文字列が格納されるはずがないことの認識がありませんでした。

用途はXmlSerealizerのラップクラスを作成しようとしていたのですが、
そもそも2.より、string型の変数の文字コードがなんであるかの指定をするということ
自体がナンセンスであったとわかりました。

public static string SerializeToString(object obj)
public static string SerializeToString(object obj, Encoding encoding) // いらない
public static T DeserializeFromString<T>(string xml)
public static T DeserializeFromString<T>(string xml, Encoding encoding) // いらない

以上ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -