DBに入っている文字列(EUC-JP)をUTF-8にエンコードするとき、「™」や「é」などの特殊な文字が化けてしまいます。

化けない方法を教えてください。
言語: PHP4.3.10
DB: Postgresql8.3.1

実際に使っているソースは以下の通りです。

$src = "EUC-JP文字列";
$src = mb_convert_encoding($src,"sjis-win","EUC-JP");
$src = mb_convert_encoding($src,"UTF-8","sjis-win");

回答の条件
  • 1人10回まで
  • 登録:2008/08/04 14:57:25
  • 終了:2008/08/11 15:00:02

回答(6件)

id:pahoo No.1

pahoo回答回数5960ベストアンサー獲得回数6332008/08/04 15:44:33

ポイント19pt

まず、EUC-JPで扱える文字は、原則として、JISコード表(JIS X 0208)に掲載されているものに限られます。

「™」や「é」は JIS コード表にない文字ですから、PHPに限らず、大多数の開発環境で変換できないでしょう。(DBのカラムもchar型で定義していたら代入できない場合があります)


このため、radreさんがご利用の PostgreSQL に「™」がどのような文字コード(EUC-JPコード)で格納されているのか分かりませんが、それをUTF-8に変換したいのであれば、str_replace関数を使って行います。

str_replace(「™」のEUC-JPコード, "\x21\x22", $src);

他の変換できない文字についても、逐一、str_replace関数で変換してやる必要があります。

id:radre

素早い返事ありがとうございます!

なるほどー。そういうことなんですね。

「™」のEUC-JPコードって、公式には定義されていないんですよね。調べる方法はあるのでしょうか。

2008/08/04 16:29:14
id:pahoo No.2

pahoo回答回数5960ベストアンサー獲得回数6332008/08/04 17:00:40

ポイント19pt

#1のコメントに対する回答

調べる方法はあるのでしょうか。

PostgreSQL から取り出した直後の文字列 $src に対し、下記のように ord 関数を使って文字コードを調べるのがよいでしょう。

$len = strlen($src);
for ($i = 0; $i < $len; $i++) {
	$ch = substr($src, $i, 1);
	printf("%02X<br />\n", ord($ch));
}

このプログラムでは1バイトずつの表示になってしまいますが、問題の「™」がEUC-JPの1バイト目の条件(0xA1 - 0xFE)を守っているかどうか分からないので、まずは目視で確認してみてください。


回答回数の上限になりましたので、これにて失礼します。

id:radre

素晴らし過ぎます(T T)

ありがとうございました!

試したところ、「™」は

8F

A2

EF

となっていました。「8F」は0xA1 - 0xFEではないですよね・・・orz

こういう場合、どうすればいいでしょうか?

解答回数を増やしましたので、ご返事いただければ幸いですm(_ _)m

2008/08/04 17:48:36
id:y-kawaz No.3

y-kawaz回答回数1421ベストアンサー獲得回数2262008/08/04 17:36:58

ポイント18pt

元エンコード指定を EUC-JP ではなく eucjp-ms を指定して mb_convert_encoding すればいいんじゃないでしょうか?

id:radre

それをすると、「™」や「é」などの記号は表示されるのですが、今度は「鵰」などの漢字が化けてしまうのです。

これらを両立する方法を探しているのです。

2008/08/04 17:44:32
id:practicalscheme No.4

practicalscheme回答回数157ベストアンサー獲得回数422008/08/04 18:38:30

ポイント18pt

そのものずばりの回答ではないので、コメント欄を開けて置いていただければ良かったのですが。

0x8f 0xa2 0xef は正当なEUC-JPコードです。0x8fから始まる2オクテットにJIS X 0212 (補助漢字) が割り当てられていて、この場合は補助漢字の0x226F (小さいTM)が相当します。eucjp-msもだいたい同じです。

しかし、eucjp-msで「鵰」(EUC: 0xfede, Unicode: U+9d70)が化けてしまうというのはわかりません。JIS X 0208の文字なので特に問題が起こりそうにないのですが… もしかすると別の文字か異体字を意図されているのでしょうか。

id:radre

ありがとうございます。

勉強になります。

2008/08/05 17:14:57
id:pahoo No.5

pahoo回答回数5960ベストアンサー獲得回数6332008/08/05 17:12:52

ポイント18pt

#2のコメントに対する回答

原始的ですが、下記のように1文字ずつ変換していくのが確実ではないかと思います。

str_replace("\x8F\xA2\xEF", "\x21\x22", $src);

mb_convert_encoding 関数は完全ではありません。

公式リファレンス「サポートされる文字エンコーディング」によると eucJP-ms をサポートしていません。


あとは、外部プログラムを使って変換する方法が考えられますが、eucJP-ms を漏れなく UTF-8 に変換できるツールというものが存在するのかどうか分かりません。

どなたかフォローをお願いします。

id:radre

ありがとうございます。

eucJP-msはサポートしてないんですねー。

むむむ。

EUC-JPからUTF-8に変換している方は通常どうされているのでしょうね。特殊文字とか使う機会がないから無視されているのかな?

2008/08/05 17:16:47
id:i_kumagoro No.6

i_kumagoro回答回数170ベストアンサー獲得回数582008/08/05 22:49:59

ポイント18pt

シフトJISではJIS X 0212に含まれる文字は原則として扱えません。sjis-winで「鵰 (practicalschemeさんの回答にはJIS X 0208な文字と書かれていますが、実際にはJIS X 0208には含まれていません)」が扱えるのは拡張文字に含まれている為です。逆に言えば、拡張文字にない「™」や「é」は扱えないということです(JIS X 0213とかを使えれば話は変わりますが、PHPがサポートしていないはずです)。

回避するには「シフトJISを経由しない」事しかないと思います。手元の環境(PHP 5.2.5)では以下のコードで「鵰」も「™」も文字化けしませんでした。

$src = mb_convert_encoding($src,"UTF-8","EUC-JP");
id:radre

ありがとうございます。コメントあわせて読みました。文字コードは奥が深すぎます。。。

2008/08/09 12:54:11
  • id:pahoo
    (#5のコメント)> 特殊文字とか使う機会がないから無視されているのかな?

    仕事でSJISやEUC-JPをベースにしたシステムを設計するときは、かならず、JIS第一・第二水準(JIS X 208)以外は入力させないようにしています。自社開発のアプリが対応できても、連携する他社アプリが対応していなかったり、ブラウザによっては文字化けを起こすことがあるためです。
    ご質問のようにJIS補助漢字(JIS X 0212)を使う必要がある場合は、最初からUnicodeで設計します。それでもブラウザによって文字化けを起こすことがあるんですけどね(苦笑)。
    日本の人名では、Unicodeを使っても表示できない漢字があります。こんなときは、\xではじまるようなエスケープシーケンスで対応することもあります。そのため、ブラウザやプリンタに対応フォントがない場合に代替文字(正字や常用漢字)を表示するモジュールをつくりました。
    ご参考まで。
  • id:i_kumagoro
    すみません、一ヶ所訂正です。
    もし回答をオープンされた場合は、"EUC-JP"を"eucJP-win"と読みかえてください。
    よく読んだら「鵰」がJIS X 0212文字として書かれているか不明でした。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません