php で文字コード変換のエラーを拾いたい、という話。
ありていに言うと、webページはUTF-8だけど、 DB が euc-jp なので、 euc-jp でない入力は事前にチェックしたいのねん。 で、こんなテストを書いてみた。 UTF-8 では表示できる簡体字を入力にして、 EUC-JP に変換して、ありゃ失敗だよ、とやりたい。 「書」も「芸」も、簡体字は日本語にない文字なので、こんな風に書いてみる (例えば「機」の簡体字は「机」なので日本語にある)。 $str = "\xE4\xB9\xA6"; // 「書」の簡体字(UTF-8) 困ったことに、これでは TRUE が返る。 mb_convert_encoding は例外も出さないし、エラーも出さないし、 無理やり変換してくれる。 ちなみに変換結果は「??」になる。 化けてるんじゃなくて、本当に「?」が2つという、 なんなんだよそれwww!という動作。 次に iconv を試してみる。 上記の mb_convert_encoding の部分をこんな風に書き換える。 $str2 = iconv("UTF-8", "EUC-JP", $str); ちなみにこちらも、コマンドラインに Notice は出すものの、 例外もエラーも出さない。 この場合は、$str2 が FALSE になる。 しかし、入力文字列がもっと長くて、途中まで変換できちゃった場合には、 変換できたところまでが $str2 に入ってしまうようなので、 $str2 == FALSE という判断ができない。 変換後と変換前とで、長さを比べることもできないしなぁ (変換に成功すると UTF-8 の方が長くなる)。 成否判定部分を perl みたいに書いてみたりもしたのだが。 // (ASCII | 半角カナ | 3バイト | 2バイト)+ これだと、EUC-JP の文字でも FALSE が返ってしまう。 正規表現間違ってないよね? iconv が吐いた字をファイルに落としてみたら、 簡体字がちゃんと GB2312 に変換されていた。 気利かせすぎ! EUC-JP にならないなら、素直に諦めてくれて良いんだってば! 困ったなぁ。 みんなはどうしてるんだろう??? 追記: コメントにて、解決方法のご提案を頂きました。 ★方法1:mb_check_encoding を使う PHP: mb_check_encoding - Manual 上記マニュアルによると、 バイトストリームが指定したエンコーディングで有効なものかどうかを調べます とあります。 残念ながら、これは今回の目的には合致しません。 今回の困っている点は、 ・mb_convert_encoding では、変換結果にホントに「??」という文字列を出してくる ・iconv では、文字コード変換を途中までちゃんとやってくれる なのですが、これで出力された文字列は euc-jp で有効なので、 変換に失敗したかどうかはわかりません。 でも使えそうな関数なので、 覚えて置いて損はないなぁと思いました。 ★方法2:可逆かどうかで判断 utf-8 → euc-jp へ変換し、 変換後の文字列を euc-jp → utf-8 へ変換し、 最初と最後が同じか、比較する、というものです。 なるほど、これならちゃんと FALSE が返ります。 すごく効率的!という感じはちょっと減りますが、確実な感じはしますね。 ★方法3:mb_detect_encoding を使う mitsukenさんからこの関数は如何でしょう?とご提案を頂きました。 PHP: mb_detect_encoding - Manual 検出した文字エンコーディングを返しますだそうです。 文字コード変換自体を行うわけではないので、 文字コード変換後に、変換結果が正しいか、判定するのに使うのだと思います。 が、これも方法1と同様で、 mb_convert_encoding も iconv も一部分は正しく変換してくるので、 結果として全部は変換できていないのに、 変換された一部分は euc-jp としては本当に「正しい」のです。 だから、最後まで全部変換できたのかどうかは、 これでは判定できないと思います。 うーん難しい。 ☆ちょっと横道 文字をバイトで指定するときは $str1 = b"\xE4\xB9\xA6"; のようにしたら良いですよとアドバイスを頂きました。 これは PHP5.2.1 からの機能のようです。 バージョンがこれ以上なら使えそうですね。
by xiaoxia
| 2007-07-12 18:22
| プログラム言語
|
カテゴリ
以前の記事
2022年 12月 2021年 05月 2019年 12月 2018年 12月 2018年 05月 2018年 03月 2017年 03月 2017年 02月 2016年 08月 2016年 04月 more... 最新の記事
最新のトラックバック
ライフログ
今読んでる
その他のジャンル
記事ランキング
ブログジャンル
|
ファン申請 |
||