今どきPHPでシステムを組む場合、ほぼUTF-8で作ることになります。
UTF-8はSJISと違って文字化けの心配もなくて安心ですが、CSVファイルにする場合だけは勝手が違います。
PHPの文字コードがUTF-8のままCSVファイルを生成すると、エクセルで開いたときに日本語の部分が文字化けしてしまいます。
これはエクセルが強制的にSJISで開いているから起きているんです。
これでは、使い物にならないので、CSVを生成するときにひと手間加える必要があります。
今回は、日本語が入った配列データを文字化けせずにCSVファイルに保存する方法を紹介します。
[box class=”pink_box” title=”他の文字コードからSJISに変換する場合”]
UTF-8ではなく、ほかの文字コードからSJISに変換する場合は、UTF-8となっている部分を対象の文字コードに変換すればOKです。
[/box]
日本語が入った配列データを文字化けせずにCSVファイルに保存する方法
今回は以下の配列データをCSVファイルに保存します。
1 2 3 4 | $data = [ [ '日本語' , '文字化け対応' , 'テスト' ], [ '日本語' , '文字化け対応' , 'テスト' ], ]; |
stream_get_contentsを使う方法
stream_get_contentsを使う場合、以下のような関数を作ります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 | /** * CSVを生成 * @param array CSVに変換する2次元配列 * @param string CSVの保存先 */ function create_csv( $data , $save_path ) { //一時データを開く $fp = fopen ( 'php://temp' , 'r+b' ); //fputcsvでCSVデータを作る foreach ( $data as $val ) { fputcsv ( $fp , $val ); } //ファイルポインタを先頭に戻す rewind ( $fp ); //ストリームの中身をテキストデータに変換、 //さらにテキストデータをUTF-8からSJIS-winに変換する $str = str_replace (PHP_EOL, "\r\n" , stream_get_contents( $fp )); $str = mb_convert_encoding( $str , 'SJIS-win' , 'UTF-8' ); //一時データのファイルポインタを閉じる fclose( $fp ); //CSVファイルを生成して、データを書き込んで保存する $fp2 = fopen ( $save_path , "w" ); fwrite( $fp2 , $str ); fclose( $fp2 ); } |
スクリプトはは長いですが、CSV用のデータを一括でUTF-8からSJIS-winに変換しています。
あとは以下のように実行すれば、CSVファイルが生成されます。
1 2 3 4 5 6 7 8 | $data = [ [ '日本語' , '文字化け対応' , 'テスト' ], [ '日本語' , '文字化け対応' , 'テスト' ], ]; $save_path = "sample.csv" ; create_csv( $arrays , $save_path ); |
mb_convert_variablesを使う方法
mb_convert_variablesを使って、配列をつどUTF-8からSJIS-winに変換する場合は、以下のように関数を作ります。
あとは以下のように実行すれば、CSVファイルが生成されます。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 | /** * CSVを生成 * @param array CSVに変換する2次元配列 * @param string CSVの保存先 */ function create_csv( $data , $save_path ) { //保存するファイルのファイルポインタを開く $fp = fopen ( $save_path , "w" ); //fputcsvでCSVデータを作る foreach ( $data as $val ) { mb_convert_variables( 'SJIS-win' , 'UTF-8' , $val ); fputcsv ( $fp , $val ); } //ファイルポインタを閉じる fclose( $fp ); } |
mb_convert_variablesを1レコード単位で実行するため、レコード数が多いと速度に影響が出てきます。
1 2 3 4 5 6 7 8 | $data = [ [ '日本語' , '文字化け対応' , 'テスト' ], [ '日本語' , '文字化け対応' , 'テスト' ], ]; $save_path = "sample.csv" ; create_csv( $arrays , $save_path ); |
コメント