- ベストアンサー
C#(.Net)におけるエンコードのバグ?
- 複数のテキストファイルを読み込み、置換などの処理を加えた後に、文字コードはそのままで別名保存するアプリケーションを開発しています。
- しかし、Encodingクラスを使って文字コードを変換するところでつまずきました。EUC-JPとShift_JISを変換するときだけ、一定の文字列が文字化け(あるいは脱字)してしまいます。それも必ず化けるわけではないようです。
- 文字コードを取得したり、元の文字コードに戻すために、かなり回りくどいコードになってしまいました。代替策をお教えいただければ幸いです。
- みんなの回答 (6)
- 専門家の回答
質問者が選んだベストアンサー
> それからさらに元のエンコードに変換しようとすると、おかしなことになってしまいます。 何度もいいますが、一回でも間違ったエンコーディングで変換したらその時点で化けているのでもうどうしようもありません。だから化ける前のデータ (ファイルに保存されている生のバイト列) を正しいエンコーディングで変換する必要があります。 > エンコードの判別をする関数はあるのですが、そのためにはまずファイルを読み込まなければなりません。しかし、ファイルのエンコードがわからないので、Unicodeで読み込んでいます。 なんだか奇妙な方法でエンコーディングの判別をしているように思います。最初はエンコーディングが分からないんだから、とりあえず ReadAllBytes などを使って生のバイト列を取り込み、それをエンコーディング判定ルーチンに渡して、正しいエンコーディングが分かってからバイト列から文字列にデコードするのが筋ですよね。いきなり Unicode で読み込んだって、どうしようもないでしょう? それともその判定ルーチンがバイト列ではなく文字列から判別するなどという訳の分からない作りになっているのでしょうか。 > 2度読み込むことになってしまいますが、それしか方法はないのでしょうか? デコードする前の生のバイト列を取っておけばファイルからの読み込みは一応一回だけですみます。 byte[] bytes = File.ReadAllBytes("test1.txt"); Encoding encoding = ???; // ここで bytes からエンコーディングを判定 string text = encoding.GetString(bytes); File.WriteAllText("test2.txt", text, encoding);
その他の回答 (5)
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
#3>それからさらに元のエンコードに変換しようとすると、おかしなことになってしまいます。 だから、取り込んだものを使うのでなくて、読み込み直します。
補足
となると、2度読み込むことになってしまいますが、それしか方法はないのでしょうか? 確かにその方法ならうまくいきますが、代替策にしてもかなり気が引けますし、根本的な解決にはなっていない気がします。
- Tacosan
- ベストアンサー率23% (3656/15482)
使われているエンコーディングを自動的に正しく推定する方法は存在しません. 従って, ユーザがエンコーディングを指定しない限りどうしても誤ってしまう可能性があるということは当然承知の上だと思います. その上で, かつ Encode.Unicode でどのように読み込むのか知らないので完全に憶測になりますが, 見た感じでは Unicode の surrogated pair にあたるところの文字が読めていない感じがします. 例えば「象」という文字は EUC では BEDD というコードを持ちます. これを上下のバイトをスワップして UTF-16 として解釈すると DDBE というコードを持つ文字になりますが, これは surrogated pair の 2文字目にあたるので単独で存在することはありません (必ず surrogated pair の 1文字目のコードを持つ文字がその前にあるはずです). そのためにこの文字が削除されているという可能性があります. 「裳象」で「象」の文字が消えなければこの可能性は高そう.
- BLUEPIXY
- ベストアンサー率50% (3003/5914)
>test1.txtの文字コードは不定です。EUC-JPとは限りません。 >「test1.txt」、文字コードはEUC-JPとします。 ? もし、エンコードの判別をされているのであれば、判別がついてから#1と同様のやりかたで読み直すのがよろしいと思います。
補足
エンコードの判別をする関数はあるのですが、そのためにはまずファイルを読み込まなければなりません。 しかし、ファイルのエンコードがわからないので、Unicodeで読み込んでいます。 それからさらに元のエンコードに変換しようとすると、おかしなことになってしまいます。 「EUC-JPとする」というのはチェック時の前提です。
- UKY
- ベストアンサー率50% (604/1207)
> test1.txtの文字コードは不定です。EUC-JPとは限りません。 質問文にあるコードでは EUC に決め打ちしていたので私もそれに倣っただけです。 > 提案されたコードでは問題解決にはなりません。 そもそも何が「問題」なのかよく分からないのですが。 なぜ化けるのかが分からないのですか? それなら先の回答でもちょっと言いましたが、間違ったエンコーディングで読み込んだらその時点で化けているのでそれを更に変換したりしても元には戻りません。 それとも文字コードを取得する方法が分からないのですか? もしかして文字コードを自力で判別しようとしてますか? 何が問題なのかも分からずに「代替策」など出せるはずがありませんので情報をよろしくお願いします。もし質問者さん自身 何が問題か分からないというのであればエンコーディングや文字列・バイト列などの概念についてもっと勉強してくださいとしか言いようがありません。
補足
決め打ちはしていません。「~とします」とあるように、チェックの時は仮にEUC-JPにしてください、の意です。 しかし、わかりづらい質問ですので、質問文を変えてみましょう。 文字コードのわからない複数のテキストファイルを読み込み、置換などの処理を加えた後に、文字コードはそのままで別名保存するアプリケーションを開発することになりました。あなたならどうしますか? という感じです。
- UKY
- ベストアンサー率50% (604/1207)
> string Buffer=File.ReadAllText("test1.txt",Encoding.Unicode); そりゃあ、EUC のテキストを Unicode で読んだら化けるに決まってるじゃないですか。 というか、何で Unicode が出てきたりバイト配列に戻したりするんでしょうか? 単に EUC で読んで EUC で書き出すだけですよね? Encoding eucEncoding = Encoding.GetEncoding("EUC-JP"); string text = File.ReadAllText("test1.txt", eucEncoding); File.WriteAllText("test2.txt", text, eucEncoding);
補足
質問に書いてあるとおり、test1.txtの文字コードは不定です。EUC-JPとは限りません。 ともかく、提案されたコードでは問題解決にはなりません。
お礼
> それともその判定ルーチンがバイト列ではなく文字列から判別するなどという訳の分からない作りに なっていました。Unicodeから各コードを求めようとしているようだったのですが、ご指摘の通りバイト列で判断するようにしたところ、うまくいきました。 どうもありがとうございます。