福岡拠点の香月です。
この記事はブラウザからダウンロードするCSVファイルをWebサーバー上で作成するようなPHPプログラムを開発している人向けのトピックです。
ExcelをインストールするとCSVファイル(Comma-Separeted Values)がExcelに関連づきます。テキストエディタでCSVファイルを開く場合と違い、Excelで開くと列が揃って見やすいという利点があります。やったー!
Excelやその他WindowsのアプリでCSVファイルを作成した場合、日本語も問題なく扱えます。保存して改めてExcelで開いても正しく表示されますよね。
しかし、WebからCSVファイルをダウンロードしてExcelで開いた場合に、稀に日本語が文字化けしていることがあります。
サーバー上で次のようなプログラムを組んでcsvファイルを出力します。
1 2 3 4 |
$content = ''; $content .= '番号,名前,将来の夢'; $content .= '1,太郎,サッカー選手'; $content .= '2,華子,パティシエール'; |
クライアント側で保存したcsvファイルをExcelで開くと…
残念ですね。これはCSVファイルの文字コードの違いが問題です。
Windowsのアプリでファイル保存した場合、文字コードはほぼShift-JISとなります。対して近年のWebサーバーで扱う文字コードはほぼUTF-8となっており、CSVファイルもUTF-8であることが多いでしょう。で、このUTF-8の文字コードですが、コード表上はアルファベットや記号(日本語を含む2バイト文字以外)はShift-JISと同じコード範囲を使用しています。つまり、アルファベットや記号だけで書かれたUTF-8のファイルは、Shift-JISのファイルと全く同一ということになります。
日本語Windows上のExcelでCSVファイルを読み込む場合、UTF-8とShift-JISの区別がつかないため、ExcelさんはShift-JISとして読んでしまい、日本語部分が文字化けしてしまう、ということになります。
この問題はUTF-8のCSVファイルの先頭に「BOM」をつけて出力することで回避することができます。先ほどのプログラムの先頭をこうしてBOMを追加します。
1 2 3 4 |
$content = pack('C*', 0xEF, 0xBB, 0xBF); $content .= '番号,名前,将来の夢'; $content .= '1,太郎,サッカー選手'; $content .= '2,華子,パティシエール'; |
クライアント側で保存したcsvファイルをExcelで開くと…
正しく日本語で表示させることができました。
ちなみにこのBOMはユニコードの種類によってコードが決まっています。
ユーティリティ関数としてこのような関数を1つ作っておくと便利ですよ。
1 2 3 4 5 6 7 8 9 10 |
function get_bom($code) { if ($code == 'UTF-8') return pack('C*', 0xEF, 0xBB, 0xBF); else if ($code == 'UTF16BE') return pack('C*', 0xFE, 0xFF); else if ($code == 'UTF16LE') return pack('C*', 0xFF, 0xFE); else if ($code == 'UTF32BE') return pack('C*', 0x00, 0x00, 0xFE, 0xFF); else if ($code == 'UTF32LE') return pack('C*', 0xFF, 0xFE, 0x00, 0x00); return ''; } |