以下のいずれかの情報。知っている方おしえてください。
・調べる手段
・PHP用のライブラリ
・1文字ずつ文字コードを調べる場合、なにをもって日本語として判断してよいのか?(文字コード表サイトのURLとか希望)
※プログラミングの中で利用します。ロジックならプログラム言語問わず。ライブラリならPHP用のものでお願いいたします。
あまりPHPに詳しくないので、技術資料の提示だけになりますが、
基本的には、UTF-8のままでの文字コード処理は非常に面倒なので、UCS-2(2バイト/文字)あるいは、UCS-4(4バイト/文字)への変換を行ってから、その文字コードが、日本語の文字コードの領域に収まっているかどうかを判断するということになります。しかしながら、実際のところ、感じに関しては、CJK(中国語・日本語・韓国語)統合といわれる、文字コードの共通化がなされているため、感じを見て、日本語なのか、中国語なのかを探るためにはそれなりのデータベースあるいは、アルゴリズムが必要になると思います。従って、普通の場合は、ひらがな、カタカナが含まれているかどうかを調べる方が良いのではないかと思います。
ここで、言葉について若干の説明をしておきますと、UCS-2とUCS-4は、いずれも、Unicodeの文字セットで、UCS-4は、UCS-2のスーパーセットです。つまり、UCS-4はUCS-2を含みます。もともと、Unicodeでは、16bitですべての文字にコードを割り振ろうとしていましたが、全くもって足らなかったので、最終的に、32bitのUCS-4に落ち着いたと考えていればあんまり問題はありません。また、UTF-8は、32bitのUCS-4をそのまま使うとメモリ効率が悪いので、ASCIIの文字を8bitだけでも表現できるようにいろいろと変換をこらしたものです。そのため、日本語の文字に関しては、通常は、1文字が2バイト~3バイトになります。
さて、実際の処理ですが、
1, 1文字ずつUTF-8→UCS-2(あるいは、UCS-4)への変換を行う
2, ひらがな・カタカナの領域に収まっているかどうかのチェック
になります。本来であれば、すべての情報は、http://www.unicode.org/ から手に入れることができるのですが、言葉が若干難しかったり、あるいは、日本語のリソースがないことなどが障壁になる可能性があるので、適当にGoogleで検索した参考になりそうなサイトを挙げておきます。
1に関しては、ビット操作の知識は必要ですが、
UTF-8
http://www.asahi-net.or.jp/~ci5m-nmr/w3/utf-8.html
などがわかりやすいと思われます。
2に関しては、そのままずばり、
http://www.unicode.org/Public/UNIDATA/Blocks.txt
が参考になります。これは、Unicode.org公式のUnicodeのコードブロックについての説明ですが、これを Hiragana, Katakana で検索すれば、
3040..309F; Hiragana 30A0..30FF; Katakana
というのが見つかります。つまり、この範囲の文字コードがひらがな・カタカナに該当するというわけです。
以上、純粋に技術的な資料だけですので、どこまでお役に立てるかは未知数ですが、ご確認いただければと思います。
また、以下は、C++のコードではありますが、UTF-8→UCS-4の変換を行うコードです。上記のビットの説明と併せて見てみると参考になるかもしれません。ロジックはちょっとだけ改良されているので直接の比較は難しいかもしれませんが・・・。
int get_skip_chars(unsigned char chr) { if((chr & 0x80) == 0x00) return 1; else if((chr & 0xe0) == 0xc0) return 2; else if((chr & 0xf0) == 0xe0) return 3; else if((chr & 0xf8) == 0xf0) return 4; else if((chr & 0xfc) == 0xf8) return 5; else if((chr & 0xfe) == 0xfc) return 6; } unsigned int get_UCS4_code(const unsigned char *ptr, int* skip) { const u8 *p = (const u8 *)ptr; unsigned int chr = (unsigned int)*p; if(chr < 0x80) { *skip = 1; return chr; } static const unsigned int base[] = { 0x00000000, 0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080}; int size = get_skip_chars(chr); for(int i = 1; i < size; i++) chr = (chr << 6) + p[i]; *skip = size; return chr - base[size]; } int main() { const char* test = "hello, world"; // イメージ的にはここがUTF-8の文字列 while(*test) { int skip; unsigned int code = get_UCS4_code(test, &skip); if(code >= 0x3040 && code <= 0x309f) printf("%08X: ひらがな\n", code); if(code >= 0x30a0 && code <= 0x30ff) printf("%08X: カタカナ\n", code); else printf("%08X\n", code); // その他 test += skip; } }
あまりPHPに詳しくないので、技術資料の提示だけになりますが、
基本的には、UTF-8のままでの文字コード処理は非常に面倒なので、UCS-2(2バイト/文字)あるいは、UCS-4(4バイト/文字)への変換を行ってから、その文字コードが、日本語の文字コードの領域に収まっているかどうかを判断するということになります。しかしながら、実際のところ、感じに関しては、CJK(中国語・日本語・韓国語)統合といわれる、文字コードの共通化がなされているため、感じを見て、日本語なのか、中国語なのかを探るためにはそれなりのデータベースあるいは、アルゴリズムが必要になると思います。従って、普通の場合は、ひらがな、カタカナが含まれているかどうかを調べる方が良いのではないかと思います。
ここで、言葉について若干の説明をしておきますと、UCS-2とUCS-4は、いずれも、Unicodeの文字セットで、UCS-4は、UCS-2のスーパーセットです。つまり、UCS-4はUCS-2を含みます。もともと、Unicodeでは、16bitですべての文字にコードを割り振ろうとしていましたが、全くもって足らなかったので、最終的に、32bitのUCS-4に落ち着いたと考えていればあんまり問題はありません。また、UTF-8は、32bitのUCS-4をそのまま使うとメモリ効率が悪いので、ASCIIの文字を8bitだけでも表現できるようにいろいろと変換をこらしたものです。そのため、日本語の文字に関しては、通常は、1文字が2バイト~3バイトになります。
さて、実際の処理ですが、
1, 1文字ずつUTF-8→UCS-2(あるいは、UCS-4)への変換を行う
2, ひらがな・カタカナの領域に収まっているかどうかのチェック
になります。本来であれば、すべての情報は、http://www.unicode.org/ から手に入れることができるのですが、言葉が若干難しかったり、あるいは、日本語のリソースがないことなどが障壁になる可能性があるので、適当にGoogleで検索した参考になりそうなサイトを挙げておきます。
1に関しては、ビット操作の知識は必要ですが、
UTF-8
http://www.asahi-net.or.jp/~ci5m-nmr/w3/utf-8.html
などがわかりやすいと思われます。
2に関しては、そのままずばり、
http://www.unicode.org/Public/UNIDATA/Blocks.txt
が参考になります。これは、Unicode.org公式のUnicodeのコードブロックについての説明ですが、これを Hiragana, Katakana で検索すれば、
3040..309F; Hiragana 30A0..30FF; Katakana
というのが見つかります。つまり、この範囲の文字コードがひらがな・カタカナに該当するというわけです。
以上、純粋に技術的な資料だけですので、どこまでお役に立てるかは未知数ですが、ご確認いただければと思います。
また、以下は、C++のコードではありますが、UTF-8→UCS-4の変換を行うコードです。上記のビットの説明と併せて見てみると参考になるかもしれません。ロジックはちょっとだけ改良されているので直接の比較は難しいかもしれませんが・・・。
int get_skip_chars(unsigned char chr) { if((chr & 0x80) == 0x00) return 1; else if((chr & 0xe0) == 0xc0) return 2; else if((chr & 0xf0) == 0xe0) return 3; else if((chr & 0xf8) == 0xf0) return 4; else if((chr & 0xfc) == 0xf8) return 5; else if((chr & 0xfe) == 0xfc) return 6; } unsigned int get_UCS4_code(const unsigned char *ptr, int* skip) { const u8 *p = (const u8 *)ptr; unsigned int chr = (unsigned int)*p; if(chr < 0x80) { *skip = 1; return chr; } static const unsigned int base[] = { 0x00000000, 0x00000000, 0x00003080, 0x000E2080, 0x03C82080, 0xFA082080, 0x82082080}; int size = get_skip_chars(chr); for(int i = 1; i < size; i++) chr = (chr << 6) + p[i]; *skip = size; return chr - base[size]; } int main() { const char* test = "hello, world"; // イメージ的にはここがUTF-8の文字列 while(*test) { int skip; unsigned int code = get_UCS4_code(test, &skip); if(code >= 0x3040 && code <= 0x309f) printf("%08X: ひらがな\n", code); if(code >= 0x30a0 && code <= 0x30ff) printf("%08X: カタカナ\n", code); else printf("%08X\n", code); // その他 test += skip; } }
ありがとうございます。とても参考になりました。
>漢字に関しては、CJK(中国語・日本語・韓国語)統合といわれる、文字コードの共通化がなされているため、
>漢字を見て、日本語なのか、中国語なのかを探るためにはそれなりのデータベースあるいは、アルゴリズム
>が必要になると思います。
なるほど!その情報まってました。やはりそうでしたか。
文字コードの範囲判断だけで簡単に実装できないことがわかり、頭を切り替えて考えられそうです。
>従って、普通の場合は、ひらがな、カタカナが含まれているかどうかを調べる方が良いのではないか
それも検討しました。漢字だけの単文テキストも予想されるので今回はその方法をあきらめました。
C++コードありがとうございます。コードを参考にさせていただきコード変換をして、CJKだったら日本語という判断にしてしまおう方法で検討しようと思います。(あとは別途時間を作ってCJK内でJ部分だけ判断可能なようにアルゴリズムかDBを構築を目指したいと思います。)
ありがとうございます。
|
ソースをDLして読んでみました「日本語メールを文字化けせずに送れる」というライブラリのようですが、自分が探している「言語を判別する」でなく「文字コードを判別する」なので参考になりませんでした。(自分がソースを読み切れてないだけかもしれませんが・・とほほ)
>設定次第では、日本語だけでなく各国語対応ができる(はず)
とライブラリのHPには書かれているので期待したのですが、「設定次第で他の文字コードも使えます」の感じで言語判断ではなく、文字コード判断のようでした。
CJK統合漢字を用いた文章から、日本語で記述されてある可能性について考察するならば「送りがな」に注目するとヨサゲなことが、オライリーの日本語情報処理で指摘されています。
日本語情報処理の新しい版はCJKV日中韓越情報処理になります。(情報が古いかなぁ。)
余談ですが・・・
高性能なプロセッサがメモリにアクセスできる境界を考えるならば、奇数番地にアクセスさせるようなデータを多用するのは非効率的な処理です。ラテン文字を8ビット長に最適化するのは8ビットマイコンなど処理能力の低い小規模なターゲットには有効でも、32ビットマイコンなど処理能力の高く規模の大きいターゲットに対しては懐疑的だと思います。コンパイラのオプションでデータの境界を合わせる最適化をすると、メモリ効率を考えて「ラテン文字を8ビット長にする」のは無駄な努力ともいえそうです。
もちろんプロセッサの処理能力よりも、ストリームの通信コストが高いと判断できる場合は、UTF-8みたいな「ラテン文字を8ビット長に最適化する」べきでしょうけど。
また、xyzzyのメールで教えていただいたのですが、多国語文章できちんと文字の再現ができるエンコーディングは「UTF-8Nぐらいしか存在しない。」そうです。
>CJK統合漢字を用いた文章から、日本語で記述されてある可能性について考察するならば「送りがな」
>に注目するとヨサゲなことが、オライリーの日本語情報処理で指摘されています
なんですと!気になる。読んでおきたいですね。
日本語情報処理、CJKV日中韓越情報処理、共に是非読みたいと思います。(CJKV日中韓越情報処理、高い。><)
>高性能なプロセッサがメモリに 〜省略〜
高性能なのに、悲しい話ですね。
知的好奇心的な部分があるので、実装までやって実用に耐えれるスピードがでなかったらまた別の方法を探そうと思います。
ありがとうございました。
ありがとうございます。とても参考になりました。
>漢字に関しては、CJK(中国語・日本語・韓国語)統合といわれる、文字コードの共通化がなされているため、
>漢字を見て、日本語なのか、中国語なのかを探るためにはそれなりのデータベースあるいは、アルゴリズム
>が必要になると思います。
なるほど!その情報まってました。やはりそうでしたか。
文字コードの範囲判断だけで簡単に実装できないことがわかり、頭を切り替えて考えられそうです。
>従って、普通の場合は、ひらがな、カタカナが含まれているかどうかを調べる方が良いのではないか
それも検討しました。漢字だけの単文テキストも予想されるので今回はその方法をあきらめました。
C++コードありがとうございます。コードを参考にさせていただきコード変換をして、CJKだったら日本語という判断にしてしまおう方法で検討しようと思います。(あとは別途時間を作ってCJK内でJ部分だけ判断可能なようにアルゴリズムかDBを構築を目指したいと思います。)