【PHP】日本語の配列データを文字化けせずにCSVファイルに保存する方法

今どきPHPでシステムを組む場合、ほぼUTF-8で作ることになります。

UTF-8はSJISと違って文字化けの心配もなくて安心ですが、CSVファイルにする場合だけは勝手が違います。

PHPの文字コードがUTF-8のままCSVファイルを生成すると、エクセルで開いたときに日本語の部分が文字化けしてしまいます。

これはエクセルが強制的にSJISで開いているから起きているんです。

これでは、使い物にならないので、CSVを生成するときにひと手間加える必要があります。

今回は、日本語が入った配列データを文字化けせずにCSVファイルに保存する方法を紹介します。

他の文字コードからSJISに変換する場合
UTF-8ではなく、ほかの文字コードからSJISに変換する場合は、UTF-8となっている部分を対象の文字コードに変換すればOKです。

日本語が入った配列データを文字化けせずにCSVファイルに保存する方法

今回は以下の配列データをCSVファイルに保存します。

$data = [
    ['日本語', '文字化け対応', 'テスト'],
    ['日本語', '文字化け対応', 'テスト'],
];

stream_get_contentsを使う方法

stream_get_contentsを使う場合、以下のような関数を作ります。

/**
 * 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ファイルが生成されます。

$data = [
    ['日本語', '文字化け対応', 'テスト'],
    ['日本語', '文字化け対応', 'テスト'],
];

$save_path = "sample.csv";

create_csv($arrays,$save_path);

mb_convert_variablesを使う方法

mb_convert_variablesを使って、配列をつどUTF-8からSJIS-winに変換する場合は、以下のように関数を作ります。

あとは以下のように実行すれば、CSVファイルが生成されます。

/**
 * 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レコード単位で実行するため、レコード数が多いと速度に影響が出てきます。

$data = [
    ['日本語', '文字化け対応', 'テスト'],
    ['日本語', '文字化け対応', 'テスト'],
];

$save_path = "sample.csv";

create_csv($arrays,$save_path);

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください