tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルファイルからエンコードを判定
記事No10568
投稿日: 2011/07/23(Sat) 09:47
投稿者田山
ファイルからエンコードを取得したいのですが、どのようにしたら
実現可能でしょうか?

アドバイス下さい。

宜しくお願いします。

[ツリー表示へ]
タイトルRe: ファイルからエンコードを判定
記事No10569
投稿日: 2011/07/24(Sun) 11:43
投稿者花ちゃん
> ファイルからエンコードを取得したいのですが、どのようにしたら
> 実現可能でしょうか?
>
> アドバイス下さい。
>
> 宜しくお願いします。

回答ではありません、ここで質問されるなら環境や状況等もキチンと書くようにして下さい。
(注意書き参照)

又、ファイルと一言で言っても色々なファイルがあります。
ファイルによって対応も違ってくるかと思いますが?、又条件等があるならなおさら
(単純なテキストファイルなら無理かも)

[ツリー表示へ]
タイトルRe: ファイルからエンコードを判定
記事No10570
投稿日: 2011/07/27(Wed) 08:03
投稿者shu
まずはBOM付きかどうか判断、BOM付きならファイルの先頭が
UTF-8 : EF BB BF
UTF-16 ビッグ エンディアン バイト順 : FE FF
UTF-16 リトル エンディアン バイト順 : FF FE
UTF-32 ビッグ エンディアン バイト順 : 00 00 FE FF
UTF-32 リトル エンディアン バイト順 : FF FE 00 00

で始まります。(MSDNよりコピー)


後は&H80以上のByteが最初に表れる場所を探してそこから何バイトか
取得しEncodingしてみて、判断するとか。正規表現を使うと判断出来るかも。

ファイルがテキストファイルとして完全でなければ(Binaryデータが混在)判断のしようが
ありませんので気をつけてください。

[ツリー表示へ]
タイトルRe: ファイルからエンコードを判定
記事No10571
投稿日: 2011/07/27(Wed) 14:41
投稿者魔界の仮面弁士
> どのようにしたら実現可能でしょうか?

Encoding クラスを使って

(1) ファイル先頭に、GetPreamble メソッドに合致する BOM があるか調べる。
 → 合致した場合、ほぼ間違いなく、そのエンコードであると確定する。

(2) Encoding.GetEncoding で、DecoderExceptionFallback を指定しておき、
 複数のエンコードをそれぞれ試してみる。
 → 文字列へと復号化する際、例外が発生したエンコードは誤りであると確定する。

のように判定すれば、ある程度の絞り込みはできるでしょう。



> アドバイス下さい。
> 宜しくお願いします。

同じバイナリが複数のエンコードで復元できてしまう事も少なくないため、
確実な判定方法という物は存在しません。上記の手法で可能性の高いものを
探し出すことぐらいはできるでしょうけれども。


たとえば、http://bit.ly/plP09U という商品を表すために、Shift_JIS エンコードで
「POLYPHONY+YRs-1000」と記述された 18 バイトのテキストファイルがあるとします。

Shift_JIS のままデコードすれば、元の「POLYPHONY+YRs-1000」に復元出来ますが、
誤って UTF-7 でデコードした場合、「POLYPHONY愛1000」という文字列に化けてしまいます。

これは、UTF-7 の「愛」が 2B 59 52 73 2D であると同時に、
Shift_JIS の「+YRs-」も 2B 59 52 73 2D で表されるからです。


あるいは、「珎瑕」と記述された 4 バイトの Shift_JIS ファイルがあるとします。
バイナリでいうと E0 DD E0 EA です。
Shift_JIS のままデコードすれば、元の「珎瑕」に復元する事が出来ますが、
誤って EUC-JP でデコードした場合、「珈琲」という文字列に化けてしまいます。

Shift_JIS と EUC-JP では、半角カナの領域および一部の漢字領域が
互いに異なる文字にマッピングされているためです。



さらに言えば、Unicode 先頭の BOM についても、厳密に言えば
必ずしも確実な手段とは言い切れなかったりします。

[ツリー表示へ]
タイトルRe^2: ファイルからエンコードを判定
記事No10572
投稿日: 2011/07/27(Wed) 15:32
投稿者魔界の仮面弁士
> (1) ファイル先頭に、GetPreamble メソッドに合致する BOM があるか調べる。
>  → 合致した場合、ほぼ間違いなく、そのエンコードであると確定する。
(中略)
> さらに言えば、Unicode 先頭の BOM についても、厳密に言えば
> 必ずしも確実な手段とは言い切れなかったりします。


上記について補足。

[RFC2781: UTF-16, an encoding of ISO 10646]
http://www.akanko.net/marimo/data/rfc/rfc2781-jp.txt


上記によると、UTF-16 の符号化は、下記の 3 種類で示されるようです。
 (1) UTF-16BE
 (2) UTF-16LE
 (3) UTF-16

これらと BOM (バイト順序マーク)の関連性を見てみると、
 ≪BOM を付与しない≫ ……… (1), (2)
 ≪BOM を付与しても良い≫ … (3)
という違いがあります。

BOM の有無まで考慮すれば、(3) はさらに
 (3.1) UTF-16のBOMなし
 (3.2) UTF-16のビッグエンディアンなBOM付き
 (3.3) UTF-16のリトルエンディアンなBOM付き
に分かれます。合計 5 種類ですね。


さてここで、バイナリの内容が
 (a) 00 41 00 42 00 43 FE FF
 (b) 41 00 42 00 43 00 FF FE
 (c) FE FF 00 41 00 42 00 43 FE FF
 (d) FF FE 41 00 42 00 43 00 FF FE
で表される 4 つのテキストファイルがあったとします。

これらを上記の 5 種類でデコードする場合、
 ◎ 4文字のデータ "ABC" & ZWNBSP
 ☆ 5文字のデータ ZWNBSP & "ABC" & ZWNBSP
 × 変換エラー
の 3 パターンいずれかになります。

なお、上記にある ZWNBSP というのは不可視文字であり、
VB.NET では「Dim ZWNBSP As Char = ChrW(&HFEFF)」に相当します。


┌──┰─┬─┬─┬─┐
│    ┃ a│ b│ c│ d│
┝━━╋━┿━┿━┿━┥
│ 1  ┃◎│×│☆│×│UTF-16BE
├──╂─┼─┼─┼─┤
│ 2  ┃×│◎│×│☆│UTF-16LE
├──╂─┼─┼─┼─┤
│ 3.1┃◎│×│☆│☆│UTF-16(BOMなし)
├──╂─┼─┼─┼─┤
│ 3.2┃?│?│◎│×│UTF-16(ビッグエンディアンなBOM付き)
├──╂─┼─┼─┼─┤
│ 3.3┃?│?│×│◎│UTF-16(リトルエンディアンなBOM付き)
└──┸─┴─┴─┴─┘

?が付いているのは、BOM 付きとなっているのに先頭が BOM では無い組み合わせです。
(ある意味では変換エラーなので、× と同様に扱っても良いですが)

[ツリー表示へ]