2007年5月24日
fgetcsv関数を使用した場合の文字化けについて
- array fgetcsv (
resource handle, int length [, string delimiter [, string enclosure]] ) - ExcelのCSVファイルから一行ずつ取得し、CSVフィールドを処理する関数。
第一引数:ファイルポインタ、第二引数:フィールドの最大長、第三引数:フィールドの区切り文字、第四引数、フィールドの囲い文字
PHPでfgetcsv関数を使ったプログラムを書いていたらCSVファイルの日本語が化けた。
半角文字が先頭にあれば文字が壊れずに正しく表示されるが、実用的でないので調べた。
~略~
ここでまず重要なのは最後の「enclosure と delimiter はそれぞれ1文字に限られており、もし1文字を超える文字列が指定された場合は、 最初の文字だけが使われます。」という一文。
~略~
「\t」を「\」と「t」の二文字として判断したりはしません。
次に、「enclosure (フィールド囲い子) パラメータは、別の文字を4番目のパラメータで 指定しない限り、デフォルトではダブルクォーテーショーンマークとなります。」という一文。
私はマニュアルを良く読まずに「enclosureを指定しなければ、フィールドの囲い子は「ない」として扱われると思いこんでいたため(そしてうちのサーバーではそれで問題なく動いてしまっていた)、そのスクリプトを他所様のサーバーで動かすと大量に文字化けが発生してしまいました。
この件の場合、fgetcsv()を使っている箇所は何も弄らずに、データ自体の各フィールドをダブルクォーテーションで括るようにしたところ、無事に意図通りの挙動をするようになりました。
挙動が怪しく、省略可能な区切り文字と囲み文字にもきちんとカンマ(,)とダブルクォーテーション(")を指定した方が良いということ。
文字化けが直らない場合はさらに以下。
setlocale(LC_ALL, 'ja_JP');
fgetcsv関数を実行する前に上のコードを追加する。すると大分改善されます。
それでも一部文字化けは残りました。fgetcsv関数はに依存する様です。
皆、ぶつかる事らしく以下の解答がありました。
[Re:Re:Re:Re:Re:文字化け対処方法について]
RFC4180(CSV形式のRFC)に準拠したCSVファイルをパースする関数を作りました。 ご参考程度にどうぞ。使い方は既存のfgetcsv関数と同様です。yossy [3月15日 23:05]
CSVファイルに日本語を使っても文字化けしない関数 fgetcsv_reg。
これで解消されました。
function fgetcsv_reg (&$handle, $length = null, $d = ',', $e = '"') {
$d = preg_quote($d);
$e = preg_quote($e);
$_line = "";
while ($eof != true) {
$_line .= (empty($length) ? fgets($handle) : fgets($handle, $length));
$itemcnt = preg_match_all('/'.$e.'/', $_line, $dummy);
if ($itemcnt % 2 == 0) $eof = true;
}
$_csv_line = preg_replace('/(?:\\r\\n|[\\r\\n])?$/', $d, trim($_line));
$_csv_pattern = '/('.$e.'[^'.$e.']*(?:'.$e.$e.'[^'.$e.']*)*'.$e.'|[^'.$d.']*)'.$d.'/';
preg_match_all($_csv_pattern, $_csv_line, $_csv_matches);
$_csv_data = $_csv_matches[1];
for($_csv_i=0; $_csv_i
関連記事
PHPでCSVファイルを読み込み[2007年4月3日]参考
- amethyst-web.org
- http://www.amethyst-web.org/
- PHPプロ!Q&A掲示板
- http://www.phppro.jp/
登録 投稿 [Atom]
