文字コード判定処理 – プログラミング – Home

通知
すべてクリア

[解決済] 文字コード判定処理


AVAILABLE
 AVAILABLE
(@AVAILABLE)
ゲスト
結合: 13年前
投稿: 9
Topic starter  

Windows C++ SDK

あるテキストファイルが与えられたときに、
そのファイルの文字コードを判定する
アルゴリズムを探しています。

判定したい文字コードは、
utf-8
utf-16(LE/BE)
Shift-JIS(Windows-31J,ASCII含む)
ISO-2022-JP
EUC-JP
です。

BOM付のutf-8,utf-16と、ISO-2022-JPは判定できます

現在考えている流れは、
if(BOMがある){
BOMに応じたエンコード
}else if(utf-16LEである){
utf-16LE
}else if(utf-16BEである){
utf-16BE
}else{
if(エスケープシーケンス){
ISO-2022-JP
}else{
int possible[4]={0};//u8,sj,jis,euc
{ //utf-8としてみてみる
1バイトずつ
ありえるバイトならpossible[0]++
可能性低めなら何もしない
不可能なバイトならpossible[0]=-1でループ抜ける
}
{ //shift-jisとしてみてみる
1バイトずつ
ありえるバイトならpossible[1]++
可能性低めなら何もしない
不可能なバイトならpossible[1]=-1でループ抜ける
}
{ //jisとしてみてみる
1バイトずつ
ありえるバイトならpossible[2]++
可能性低めなら何もしない
不可能なバイトならpossible[2]=-1でループ抜ける
}
{ //eucとしてみてみる
1バイトずつ
ありえるバイトならpossible[3]++
可能性低めなら何もしない
不可能なバイトならpossible[3]=-1でループ抜ける
}
possibleが一番高いものを選ぶ
}
}

このとき、utf-8テキストでもshift-jisのほうがpossibleが高くなります
どういうことでしょうか


引用未解決
トピックタグ
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

このような目的のためには1バイト(1オクテット)単位でのチェックでは不足で
連続するバイト(オクテット)の組み合わせによる妥当性を考察する必要がある。

あと、短文(1単語程度)の場合、原理的に判断不能(人間でも無理)なんだけど
その辺はどう対応する予定かな?

亜 1文字を取るとき
cp932 (shift-jis, windows-31j) だと 88 9F
euc-japan だと B0 A1
utf-8 だと E4 BA 9C

B0 A1 は cp932 だと 半角カタカナの ー。
E4 BA は cp932 だと 莠 9C も単独では cp932 の l/t octet として認められる。
のように、コードがかぶっている。

BOM に頼るのは良くない。UTF-16 なら常に BOM がついているとは限らない。
(たとえば、俺んちでは BOM つき UTF-16 での保存は禁止している)


返信引用
AVAILABLE
 AVAILABLE
(@AVAILABLE)
ゲスト
結合: 13年前
投稿: 9
Topic starter  

短文の場合に判断ミスが出てしまうのは仕方ないと思います。ここでは考えないことにし
ました。

>このような目的のためには1バイト(1オクテット)単位でのチェックでは不足で
>連続するバイト(オクテット)の組み合わせによる妥当性を考察する必要がある。

となるとどのような処理を行うべきでしょうか?

現在考えているのは
8bit目がなくてエスケープシーケンスがある→ISO2022JP
何らかの方法でUTF16を判定する
UTF-8の判定は、Wikipedia UTF-8 で何とかなりそうです。
Shift-JISとEUCJPを何らかの方法で判別する

UTF16についてはずっと困っています。
また、SJISとEUCJPもわかりません


返信引用
tetrapod
 tetrapod
(@tetrapod)
ゲスト
結合: 21年前
投稿: 830
 

この辺、自作するのは開発コストの問題で割に合わないと思うのだが・・・
自作しなきゃならない理由が何かある、のなら別だが、
俺なら libiconv とか IBM ICU とか既存のライブラリを使う。
変換元に *** を指定して、変換できたらその encoding が使われている、とするだけ。

sjis ってあっさり言ってるけど 本当に狭義の sjis を使いたいの?
本当は Windows-31j ないしは cp932 ではないの?
euc は euc-jp だけでいいの? euc-cn, euc-kr とか考えなくていいの?
などなど言い始めるとますますもって自作したくないんだが。


返信引用
AVAILABLE
 AVAILABLE
(@AVAILABLE)
ゲスト
結合: 13年前
投稿: 9
Topic starter  

SJISとは今回はcp932を指します
また、eucはjpだけでいいです。

iconvの使用ですが、インストールが必要みたいなのですが、どういうことなのでしょうか?
IBM ICUはUNICODEのみなのでやめておきます

また、iconv,ICUともにLinux用の解説しかないのでよく分かりません。

今回は自前で用意したいのですが、。。


返信引用
みい
 みい
(@みい)
ゲスト
結合: 22年前
投稿: 65
 

↓VBやC#ですけど考え方の参考にはなるのではないでしょうか。
http://dobon.net/vb/dotnet/string/detectcode.html
http://www.geocities.jp/gakaibon/tips/csharp2008/charset-check.html

…書かれている内容見れば分かると思いますが、自力判定って大変ですよ~。


返信引用
AR2
 AR2
(@ar2)
Estimable Member
結合: 5年前
投稿: 110
 

 VC系だと、COMインターフェイスの知識が必要ですが↓で簡単に検出できます。
 IMultiLanguage2::DetectInputCodepage()

 IEで文字化けしないものは大抵判別可能ですし、判別した文字コードでUNICODEにする
のも↓のメソッドで簡単に実現できるので、最近ではこういった変換を自力で行わなく
なってきたと思います。
 IMultiLanguage2::ConvertStringToUnicode()

 こういったものを独自で実装を行いたいということであれば、文字コードの特徴をじ
っくり読み込み、理解し、どういう優先度で判定していくかという設計を自力で行って
いくことになります。


返信引用
AR2
 AR2
(@ar2)
Estimable Member
結合: 5年前
投稿: 110
 

 あぁ、書いてる途中で・・・
 皆さん書かれているとおりに、自力実装はかなりしんどいです。

 検出精度を上げるには、さまざまなタイプのテキストを読み込ませて(数式が多いの
とか、カナが多いのとか、アルファベットが多いのとか・・・)どういった重み付けを
持たせて判定させるかという、利用シーンに合わせた判断が必要になるのです。
 よって、正解がありませんので一般的な回答は得にくいと言えます。

 自力実装を目指すのであれば、文字コード表をじっくり眺め、文字の分布、有効範
囲、有効文字、制御コード類、バイト数など、その特徴を抽出して行くという事が遠回
りに見えますが解決の糸口になると思います。


返信引用
AVAILABLE
 AVAILABLE
(@AVAILABLE)
ゲスト
結合: 13年前
投稿: 9
Topic starter  

ARさん、ありがとうございます。
かなり楽に解決できそうです。

皆さんありがとうございました


返信引用

返信する

投稿者名

投稿者メールアドレス

タイトル *

プレビュー 0リビジョン 保存しました
共有:
タイトルとURLをコピーしました