CSVデータを読み込む方法を紹介します。CSVデータを読み込む際、文字コードに注意が必要です。ここでは、PHPの内部エンコーディングとCSVデータの文字コードが「一致する場合」と「一致しない場合」の読み込み例を紹介します。
目次
検証パターン
パターン | PHP内部エンコーディング | 外部ファイル |
---|---|---|
1 | UTF-8 | UTF-8 |
2 | UTF-8 | SJIS |
ここでは、次のデータを読み込みます。
文字列A,文字列B,文字列C,日付,時刻
あああああ,佐藤,apple,2015/8/21,22:55
いいいいい,鈴木,orange,2015/9/11,11:25
ううううう,高橋,melon,2015/8/17,8:05
CSVデータ読み込み
文字コードが「一致する場合」
PHPの内部エンコーディングとCSVデータの文字コードが「一致する場合」の読み込み例を紹介します。
<?php
header("Content-Type: text/html; charset=UTF-8");
$filepath = __DIR__ . "/test_utf8.csv";
// 読み込みモードでファイルポインタを取得
if (($handle = fopen($filepath, "r")) !== FALSE) {
// ファイルポインタから行を取得
while (($line = fgetcsv($handle, 1000, ",")) !== FALSE) {
$records[] = $line;
}
fclose($handle);
}
var_dump($records);
array (size=4)
0 =>
array (size=5)
0 => string '文字列A' (length=10)
1 => string '文字列B' (length=10)
2 => string '文字列C' (length=10)
3 => string '日付' (length=6)
4 => string '時刻' (length=6)
1 =>
array (size=5)
0 => string 'あああああ' (length=15)
1 => string '佐藤' (length=6)
2 => string 'apple' (length=5)
3 => string '2015/8/21' (length=9)
4 => string '22:55' (length=5)
2 =>
array (size=5)
0 => string 'いいいいい' (length=15)
1 => string '鈴木' (length=6)
2 => string 'orange' (length=6)
3 => string '2015/9/11' (length=9)
4 => string '11:25' (length=5)
3 =>
array (size=5)
0 => string 'ううううう' (length=15)
1 => string '高橋' (length=6)
2 => string 'melon' (length=5)
3 => string '2015/8/17' (length=9)
4 => string '8:05' (length=4)
fgetcsv関数の引数は以下のようになります。
引数 | 概要 |
---|---|
第1引数 | ファイルポインタを指定。 |
第2引数 | CSVファイルにある最大行長を指定。 指定しないと最大行長の制限はないが遅くなる。 |
第3引数 | 区切り文字を指定。(デフォルト「,」) |
第4引数 | 囲み文字を指定。(デフォルト「”」) |
CSVデータ読み込み
文字コードが「一致しない場合」
PHPの内部エンコーディングとCSVデータの文字コードが「一致しない場合」の読み込み例を紹介します。パターン1のソースでSJISのCSVデータを読み込むと次のようにマルチバイト文字が文字化けします。
array (size=4)
0 =>
array (size=5)
0 => string '������A' (length=7)
1 => string '������B' (length=7)
2 => string '������C' (length=7)
3 => string '���t' (length=4)
4 => string '����' (length=4)
1 =>
array (size=5)
0 => string '����������' (length=10)
1 => string '����' (length=4)
2 => string 'apple' (length=5)
3 => string '2015/8/21' (length=9)
4 => string '22:55' (length=5)
2 =>
array (size=5)
0 => string '����������' (length=10)
1 => string '����' (length=4)
2 => string 'orange' (length=6)
3 => string '2015/9/11' (length=9)
4 => string '11:25' (length=5)
3 =>
array (size=5)
0 => string '����������' (length=10)
1 => string '����' (length=4)
2 => string 'melon' (length=5)
3 => string '2015/8/17' (length=9)
4 => string '8:05' (length=4)
そこで次のようにmb_convert_encoding
で文字コードを変換してから読み込んでいきます。
<?php
header("Content-Type: text/html; charset=UTF-8");
$filepath = __DIR__ . "/test_sjis.csv";
// mb_convert_encodingでCSVから取得した文字列をsjisからutf-8に変換
$buf = mb_convert_encoding(file_get_contents($filepath), "utf-8", "sjis");
// tmpfile関数で一時ファイルを作成
$handle = tmpfile();
// $bufの内容を $handleが指しているファイル・ストリームに書き込む
fwrite($handle, $buf);
// $handleのファイル位置指示子を、ファイルストリームの先頭にセット
rewind($handle);
while (($line = fgetcsv($handle, 1000, ",")) !== FALSE) {
$records[] = $line;
}
fclose($handle);
var_dump($records);
これで、パターン1と同じ結果になります。