ようこそゲスト さん ユーザー登録 ログイン

PHPについて質問です。

ある文字列 [ $prtString ] があります(マルチバイトを含む)。
この文字列は、
mb_detect_encoding($prtString);
すると
EUC-JP
が返って来ます。

この文字列をcsv形式で書き出そうと思っているのですが、

mb_convert_variables("EUC-JP","auto",$prtString);
print($prtString);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=download.csv");

とすると、問題なく文字コードEUCで書き出されるのに、

mb_convert_variables("SJIS","auto",$prtString);
print($prtString);
header("Content-Type: application/octet-stream");
header("Content-Disposition: attachment; filename=download.csv");

とすると、Shift-JISでファイルを開いても日本語が化け化けになってしまいます。

EUC-JPの文字列をSJISで書き出す方法が
何か間違っているのでしょうか?
教えて下さい。

ちなみに、上記ソースを書いたPHPソースそのものの文字コードはEUCです。
これが問題なのでしょうか?
(このソースの文字コードは変更できません)

PHPについて質問です。 ある文字列 [ $prtString ] があります(マルチバイトを含む)。 この文字列は、 mb_detect_encoding($prtString); すると EUC-JP が返って来ます。 .. を含むブックマークはてなブックマーク - PHPについて質問です。 ある文字列 [ $prtString ] があります(マルチバイトを含む)。 この文字列は、 mb_detect_encoding($prtString); すると EUC-JP が返って来ます。 .. - 人力検索はてな

  • nacbox あなたも質問に答えられます! ウォッチリストに追加
  • 状態:終了 いるか
  • 回答数:2 / 45件
  • 回答ポイント:70ポイント
  • 登録:2008-01-21 00:40:54
  • 終了:2008-01-21 23:31:13
  • カテゴリー:コンピュータコンピュータ ウェブ制作ウェブ制作

1 回答者:t_shiono 2008-01-21 00:51:20 満足! 35ポイント

ぱっと見て気になるのは、headerでの出力前にprintで出力しちゃって大丈夫?というのが気になります。

この辺りは、デバッグ中と解釈すると、その他に明らかな問題はないような気がするのですが、

$prtStringが文字列なのであれば、mb_convert_encodingを使ってはどうですか?

あとは、せっかくmb_detect_encodingで確認しているのであれば、autoではなく、EUC-JPを指定してみては如何でしょうか?

これ以外となると、PHPもしくはWebサーバ関連で出力時に文字コードの自動変換が機能しているというのが怪しい気がします。


何かの参考になれば。

質問者:nacbox 2008-01-21 00:57:00

う~ん、なるほど、明らかな問題はない、ですか……。

まぁ、もちろん、自分では問題がないつもりで作っているので困っちゃってるんですが(^^;

headerとprintの順序は関係ないみたいですね。

入れ替えても影響ないです。

EUC-JPをautoで書いているのは質問にあたり問題を複雑化しないためで、そこはEUC-JPにしてみても変わりませんでした(元はといえば、autoがいけないのかなと疑ったために、mb_detect_encodingを使ったりしたのでした)。

なるほど、文字コードの自動変換かぁ~~(^^;;

それか?

サーバの設定は分からないから、そうだとすると諦めるしか(^^;

2 回答者:ymlab 2008-01-21 01:01:54 満足! 35ポイント

http://zapanet.info/phpdoc/function.mb-detect-encoding.html

では、mb_detect_encodingで、strictモードが選択できるようになっていますが、

試されてみたでしょうか。

また、参考になるかはわかりませんが、

・私もそんな状況で困ったのですが、auto指定ではうまくいかず、autoのところを、

EUC-JPとわかっていた場合、EUC-JPときちんと指定した場合はうまくいったパターンがありました。

・mb_convert_variablesと内部的な同じ動作かもしれませんが、mb_convert_encodingも試してみてください。

・headerのContent-Typeに、charsetを指定してみたらよいかもしれません。

質問者:nacbox 2008-01-21 01:18:19

確認してみました。

・mb_detect_encoding で strict を TRUE指定しても結果は特に変わらず(=EUC-JP)

・auto を EUC-JP にする→念のため再度確認してみましたが結果に影響なし

・mb_convert_encodingにしてみる→結果に影響なし

・Content-Typeにcharsetを指定→結果に影響なし

総合して以下のように書きました。

結果は変わりません。

なんでなんだろう……。

$prtString=mb_convert_encoding($prtString,"SJIS","EUC-JP");

print($prtString);

header("Content-Type: application/octet-stream; charset=Shift_JIS");

header("Content-Disposition: attachment; filename=download.csv");

おとなり質問

この質問・回答へのコメント

回答に書き忘れましたが、SJIS指定して出力されたファイルのエンコーディングは何になっているのでしょうか?

EUCのままなのか、何故だか、UTF-8になっているとか、あるいは、全く解読できないデータになっているとかが分かると、何か解決のとっかかりになるかもしれません。
うーん、ファイルのエンコーディングって、どうやって確認するんでしょう?
とりあえず、テキストエディタで開いた際に、
EUC-JPで書き出した場合はエディタで文字コードをEUC-JPに指定してやれば日本語がちゃんと見えるのですが、
SJISで書き出した場合はエディタでどの文字コードにしても化けっぱなし、という状態です。

実際のところ、SJISにしたいと言うよりは、「書き出したCSVファイルをダブルクリックしてそのままエクセルで立ち上げた際に、日本語が文字化けせずに閲覧できること」を目的としています。
EUC-JPの文字コードで書き出されたCSVファイルは、エクセルでそのまま開くと、(たぶんエクセル側がSJISをデフォルトとしているのか)文字化けしてしまうんですよね。
複数の文字コードに対応したテキストエディタで開いてみてください。
例えばですが、秀丸やEmacsなどです。あとは、ブラウザで開くというのも簡単かもしれません。

ブラウザでの確認方法は、こんな感じです。

1.hoge.csvとして出力したファイルを、hoge.htmlなどとリネームして、ブラウザで開いてください。
2.うまくブラウザのエンコーディングの認識が機能すれば、その文字列が表示されると思います。
3.IEであれば、表示->エンコードのところで、どのエンコーディングにチェックが入っているかを確認してください。
4.もし、ブラウザで文字化けしていたら、表示->エンコードのところで、正しく表示されるものを探してください。Shift_JIS、EUC、UTF-8程度を試せば十分だと思います。

あとは、自動変換の確認ですが、サーバの設定を見れないとのことなのですが、こんな風に試してみてください。

以下のようなtest.phpプログラムをShift_JISで保存して、サーバ上に配置して、アクセスしてみてください。上記、エンコーディングの確認と同様にShift_JISとしてうまく表示されれば、サーバ側での自動変換はないかと思います。逆に、EUCなどで正しくみえれば、自動変換されていることの確証がえられます。

<?php
echo "テスト";
?>

確証が得られたところで、何かの言い訳や、クライアントさんへのお願い程度にしかならないのかもしれませんが、もやもやしているよりははっきりした方がよいと思いますので。
ああ、いえ、秀丸で確認してます。
SJISで書き出したやつは、文字コードを何にしても文字化けしっぱなし。
ブラウザで見ても同じです。
何か別の文字コードで書き出されてる(=どれかの文字コードなら見られる)と言うよりは、もう、全然正常には見られないって感じですね。

で、自動変換のほう、確認してみました。
うーん?
Shift_JISでちゃんと出ますね。
自動変換っていう訳ではないってことでしょうか。

ちょっと、もう、よく分かんないので、とりあえず明日、サーバ管理者に質問してみます。
まだ社内のテストサーバ上で、クライアントの実装サーバ上ではないので……。
休日だったので、確認のしようがなく、はてなに質問を投げたのですが、
もしも解決したら結果もこちらでご報告します。

一応質問はまだ開けておくので、何か解決策のある方がいらっしゃったら引き続きお願いします。
症状からすると、自動変換ではないようですね。
EUCではうまくいくというのが、すっきりしないですね。

mb_convert_variables()が失敗して、データを壊しているとしか思えないというか・・・。
ちなみにですが、mb_convert_variablesは成功すると、恐らくEUCという文字列を返すと思いますが、正しく返していますか?
もし、ASCIIなんかを返しているようであれば、autoのところを明示的にEUCを指定してみてください。

あとは、header()での出力をやめて、ブラウザ上にcsvデータを表示させた際はどうなりますか?
ちなみにくどいようですが、header()より先に中身を出力して、ファイルとしてダウンロードできるのが不思議です。
mb_detect_encodingの結果から疑ってみては?
あとautoも信用できないのできちんと指定した方がいいです。
とりあえず一度全部出力してみて

echo $prtString;
echo mb_convert_encoding("EUC-JP","EUC-JP",$prtString);
echo mb_convert_encoding("Shift_JIS","EUC-JP",$prtString);

どれが何の文字コードになっているのか整理しないと
環境が変わるごとに挙動が変わってキリがないと思います。
t_shionoさん、KeyKeyさん、コメントありがとうございます。
いろいろ手掛かりを提示していただいて感謝ですが、
それとは別に、解決を得ましたのでご報告いたします。

最終的なソース↓
header("Content-Type: application/octet-stream; charset=Shift_JIS");
header("Content-Disposition: attachment; filename=download.csv");
mb_convert_variables("SJIS","EUC-JP",$prtString);
mb_http_output('pass');
print($prtString);

と言うことで、
mb_http_output('pass');
を挿入することでSJIS書き出しを成功しました。

結局、最終的に出力される文字コードをEUC-JPに設定している箇所が別にあったため、
mb_http_output('pass');
することでSJIS指定のエンコードをそのまま行うように明示的に宣言する必要があったみたいです。

この質問・回答へのトラックバックこの質問・回答へのトラックバック

受注詳細CSVダウンロード for NP後払い受注詳細CSVダウンロード for NP後払い Soliloquy of Webmas 2008-10-24 10:36:17
NP後払いで注文詳細を登録する際に「csv」で登録できますが、EC-CUBEには...