Help us understand the problem. What is going on with this article?

PHPで文字化けするCSV処理を文字化けしなくする方法

結論

fw3/streamscomposer require fw3/streamsして、CSVを扱っている処理を次のように囲ってあげれば文字化けしなくなります。

※ PHP7.2.0未満(下限PHP5.3.3)で解決したい場合はfw3_for_old/streamsを利用してください。(composer require fw3_for_old/streams
  fw3/streamsおよびfw3_for_old/streams共にPHP8.0 beta 2まで動作確認済みのため、PHP7.2.0以上のシステムの場合はどちらを入れても変わりはありません。
※ composerを使用できない環境の場合は、こちらからZIPファイルをダウンロードし、展開して任意のディレクトリにコピーしてください。
  その後、使用対象となる処理より前にrequire_once sprintf('%s/src/filters_require_once.php', $path_to_copy_dir);としてsrc/filters_require_once.phpを読み込むようにしてください。

読み込み

既存の実装が次のような形の場合。

php
$fp     = \fopen($csv_file_path, 'r+b');
$data   = [];
while (($row = \fgetcsv($fp, 1024)) !== FALSE) {
    $data[] = $row;
}
\fclose($fp);

次のようにラップしてあげるだけで解決。

php
<?php

// fw3_for_oldを使用している場合は、`use fw3\`を`use fw3_for_old\` として読み替えてください。
use fw3\streams\filters\utilitys\StreamFilterSpec
use fw3\streams\filters\utilitys\specs\StreamFilterConvertEncodingSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertLinefeedSpec;

$data   = StreamFilterSpec::decorateForCsv(function () use ($csv_file_path) {
    // フィルタの設定
    $spec   = StreamFilterSpec::resource($path_to_csv)->read([
        StreamFilterConvertEncodingSpec::toUtf8()->fromSjisWin(), // Shift_JIS(Windows-31J、MS932)として読み込んでUTF-8として出力
    ]);

//// STA 元のコード
//
    $fp     = \fopen($spec->build(), 'r+b'); // ここだけ `$csv_file_path` を `$spec->build()`に書き換える
    $data   = [];
    while (($row = \fgetcsv($fp, 1024)) !== FALSE) {
        $data[] = $row;
    }
    \fclose($fp);
//
//// END 元のコード

    return $data;
});

書き込み

既存の実装が次のような形の場合。

php
$fp = \fopen($csv_file_path, 'w+b');
foreach ($rows as $row) {
    \fputcsv($fp, $row);
}
\fclose($fp);

次のようにラップしてあげるだけで解決。

php
<?php

// fw3_for_oldを使用している場合は、`use fw3\`を`use fw3_for_old\` として読み替えてください。
use fw3\streams\filters\utilitys\StreamFilterSpec
use fw3\streams\filters\utilitys\specs\StreamFilterConvertEncodingSpec;
use fw3\streams\filters\utilitys\specs\StreamFilterConvertLinefeedSpec;

$data   = StreamFilterSpec::decorateForCsv(function () use ($csv_file_path, $rows) {
    // フィルタの設定
    $spec   = StreamFilterSpec::resource($csv_file_path)->write(array(
        StreamFilterConvertEncodingSpec::toSjisWin()->fromUtf8(),   // UTF-8として読み込んでShift_JIS(Windows-31J、MS932)として出力
        StreamFilterConvertLinefeedSpec::toCrLf()->fromAll(),       // いかなる改行コードであってもCRLFとして出力
    ));

//// STA 元のコード
//
    $fp = \fopen($spec->build(), 'w+b');
    foreach ($rows as $row) {
        \fputcsv($fp, $row);
    }
    \fclose($fp);
//
//// END 元のコード
});
project-ickx
プロジェクトイクスとは"フライトアクションゲームとその周辺サービスを開発・運営する"同人サークルです。
https://ickx.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした