DOBON.NET DOBON.NETプログラミング掲示板過去ログ

アポストロフィを含むテキストの読み込み

環境/言語:[Windows 7]
分類:[.NET]

こんにちは、

いつもお世話になっています。

Visual Studio 2010を使い始めて7ヶ月以上たちます。今まで全く気付かなかったのですが、apostrophe(')を含むテキストファイル(.txt)を開くと、apostropheだけが�に化けてしまうことがあるようです。必ずしも文字化けが起きる訳ではなく、
どうもこの文字化けはマックで作成したテキストファイルを開いた時だけ起きるようです。ちなみにファイルは以下のように読んでいます。

For Each file As String In OpenFileDialog1.FileNames
   Dim objReader As New System.IO.StreamReader(file)
   RichTextBox1.Text = objReader.ReadToEnd
   objReader.Close()
...
...
...
Next

もしかしてEncodingの型を指定して読めば文字化けがなくなるかと色々試しましたが、状況は変わりません。例えば、Encoding.GetEncoding("macintosh")だと、apostropheは(確か)íのような文字に置き換えられてしまいます。

インターネットで検索してみましたが、今のところ似た様な書き込みに出くわしていません。Replace(objReader.ReadToEnd,"�","'")とやるのは最後の手段ですが、ほかにapostropheをうまく読む方法はあるでしょうか?

尚、�は黒い?の文字、íはiにアクセントのついた様な文字です。

以上宜しくお願いします。
回答ではありません。

そのテキストファイルはUTF-8なのでしょうか?
そのテキストファイルをバイナリエディタで開いた場合、アポストロフィが入っているはずのところにはどんなバイナリが格納されていますか?
あと、質問文の&#〜;は実際に&で始まる文字列ではなくHTMLの都合で、実際には文字U+FFFDなどってことでいいですよね?(Encodingクラスに勝手にHTMLエンコードしちゃう機能はないですし)
■No30624に返信(Hongliangさんの記事)
> 回答ではありません。
>
> そのテキストファイルはUTF-8なのでしょうか?
> そのテキストファイルをバイナリエディタで開いた場合、アポストロフィが入っているはずのところにはどんなバイナリが格納されていますか?
> あと、質問文の&#〜;は実際に&で始まる文字列ではなくHTMLの都合で、実際には文字U+FFFDなどってことでいいですよね?(Encodingクラスに勝手にHTMLエンコードしちゃう機能はないですし)


どうも早速の返答、ありがとうございます。

バイナリエディタに関してですが、今、Windowsを使っていないので返答を差し控えます。Windowsのソフトは全く使わないですし。

&#〜の件ですが、おっしゃる通りです。「プレビュー」で本文を確認した時に、それらの記号を正しく表示できるエンコードを自分のマック用のウェブ・ブラウザーで指定していないためか、或はサイトで使われているText Encodeのせいなのか、それらの文字がHTMLの記号で現れることがわかっていました。そこで説明を付けてそれらのHTMLの記号に説明をつけただけです。
■No30623に返信( 缶吉さんの記事)
>    Dim objReader As New System.IO.StreamReader(file)
上記のコードは、UTF-8 で書かれたテキストファイルを読むために使います。

そのため、元データがUTF-8 のファイルであるかどうかを事前に調査し、
そうでない場合は適切な Encoding を指定せねばなりません。

たとえば、Latin-1 でエンコードされたテキストファイルを
UTF-8 でデコードしようとすれば、シングルクォーテーションなどが
別の文字に化けてしまう結果になるはずです。

ゆえに今回は、どのソフトで生成されたファイルなのか、その時のエンコードは
何が使われているのかを調べることが重要となります。それが分からない場合は、
元ファイルのバイナリを見て判断してみてください。


> 尚、�は黒い?の文字、íはiにアクセントのついた様な文字です。
間違った Encoding を指定したことで、代替文字に化けてしまっていますね。

前者は U+FFFD : REPLACEMENT CHARACTER、VB で言えば ChrW(&HFFFD) の文字です。
UTF-8 でエンコードした場合は EF,BF,BD というバイナリになります。
http://www.fileformat.info/info/unicode/char/fffd/index.htm

後者は U+00ED : SMALL LETTER I WITH ACUTE。ChrW(&HED) ですね。
UTF-8 では、C3,AD のバイナリで表現されます。
http://www.fileformat.info/info/unicode/char/ed/index.htm



> 色々試しましたが、状況は変わりません。
Encoding.GetEncoding する際に、GetEncoding の第2・第3引数に、
EncoderExceptionFallback/DecoderExceptionFallback クラスを
渡してみてください。

そうすると、指定した Encoding では変換できない文字があった場合に
文字化けさせるのではなく、変換に失敗する不正なデータが
例外として検出されるようになります。


> apostrophe(')を含むテキストファイル(.txt)を開くと、
仮に、元ファイルの文字コードが Latin-1 すなわち ISO/IEC 8859-1 だったとしてみましょう。

Latin-1 は、ラテンアルファベットで標準的な欧文用文字コードですが、
これにはシングルクォーテーションに相当する文字として
 0x27 APOSTROPHE                  …「'」
 0x91 LEFT SINGLE QUOTATION MARK  …「‘」に似た文字
 0x92 RIGHT SINGLE QUOTATION MARK …「’」に似た文字
などが用意されています。Unicode でいえば、これはそれぞれ
 U+0027 APOSTROPHE
 U+2018 LEFT SINGLE QUATATION MARK
 U+2019 RIGHT SINGLE QUATATION MARK
にあたります。

これらの文字は、ISO-8859-1 から UTF-8への変換の場合は、
 27 → 27
 91 → C2,91
 92 → C2,92
にマッピングされることになっています。
# ただし UTF-8 自体には、1 バイト単独で 91 というデータはありえません。
# C2,91 のように、マルチバイト文字の後続バイトになることはあります。

また、ISO-8859-1 から Shift_JIS への変換の場合、
 27 → 27
 91 → 該当文字なし
 92 → 該当文字なし
です。このようなケースでも文字化けが発生することになります。


'下記は Latin-1で「A'B‘C’D」を表すバイナリです。(実際にはすべて半角文字)
Dim bin() As Byte = {&H41, &H27, &H42, &H91, &H43, &H92, &H44}

'それを、誤った文字コード(ISO-8859-1 以外)を指定してデコードすると、
'正しく変換されず、文字化けや文字欠けが発生します。
Dim badUTF8 As String = Encoding.UTF8.GetString(bin)
Dim badSJIS As String = Encoding.GetEncoding("Shift_JIS").GetString(bin)

'正しい文字コードを指定すれば、正しくデコードされます。
'(画面に表示する場合には、対応する欧文フォントも必要です)
Dim s As String = Encoding.GetEncoding("iso-8859-1").GetString(bin)
TextBox1.Text = String.Format("Length={0}, String={1}", s.Length, s)

'正しくデコードされば文字列を UTF-8 でデコードすることはできます。
'この場合、91 → C2,91 に変換されることになります。
Dim utf8() As Byte = Encoding.UTF8.GetBytes(s)

'Shift_JIS への変換では、91 や 93 などは代替文字に置き換わってしまいます。
Dim sjis() As Byte = Encoding.GetEncoding("Shift_JIS").GetBytes(s)
魔界の仮面弁士 さん、

はじめまして。どうも詳しい説明をありがとうございます。いつも魔界の仮面弁士さんの書き込みの詳細な説明に感心しています。

確かdobonさんでEncoderExceptionFallback/DecoderExceptionFallbackを使ったコードの例をみたことがあると思います。この線で調べてみます。

どうもありがとうございました。
解決済み!

DOBON.NET | プログラミング道 | プログラミング掲示板