Webエンジニア向けプログラミング解説動画をYouTubeで配信中!
▶ チャンネル登録はこちら

【PHP8.x】fgetcsv()関数の使い方

fgetcsv関数の使い方について、初心者にもわかりやすく解説します。

作成日: 更新日:

基本的な使い方

『fgetcsv関数は…を実行する関数です』

fgetcsv関数は、fopen関数などによって開かれたファイルポインタから、CSV(Comma-Separated Values)形式のデータを1行ずつ読み込み、それを配列として解析する関数です。この関数は、CSVファイルの内容をプログラムで効率的に処理する際に広く利用されます。第一引数には、対象となる有効なファイルポインタを指定します。関数が呼び出されるたびに、ファイルポインタは次の行へと自動的に進みます。オプションの引数として、フィールドの区切り文字(デリミタ、デフォルトはカンマ)、フィールドを囲む文字(エンクロージャ、デフォルトはダブルクォーテーション)、そして読み込む行の最大長を指定することが可能です。正常に1行を読み込めた場合、各フィールドの値を要素として持つ配列を返します。ファイルの終端に達した場合や、読み込みエラーが発生した場合は false を返します。そのため、while ループと組み合わせて、ファイルの内容がなくなるまで繰り返し処理を行うのが一般的な使い方です。なお、PHP 8.0.0以降では、空行を読み込んだ場合は [null] という単一の null 値を含む配列が返されます。

構文(syntax)

1fgetcsv(
2    resource $stream,
3    ?int $length = null,
4    string $separator = ",",
5    string $enclosure = "\"",
6    string $escape = "\\"
7): array|false

引数(parameters)

resource $stream, ?int $length = null, string $separator = ',', string $enclosure = '"', string $escape = '\'

  • resource $stream: 読み込むCSVデータが含まれるファイルリソースを指定します。
  • ?int $length = null: 1行あたりに読み込む最大バイト数を指定します。省略すると、最大行長に制限はありません。
  • string $separator = ',': CSVの各フィールドを区切る文字を指定します。デフォルトはカンマ(,)です。
  • string $enclosure = '"': CSVのフィールドを囲む文字を指定します。デフォルトはダブルクォーテーション(")です。
  • string $escape = '\': $enclosure文字をエスケープするために使用される文字を指定します。デフォルトはバックスラッシュ()です。

戻り値(return)

array|false

fgetcsv関数は、ファイルポインタから1行を読み込み、CSV形式のデータを配列として返します。ファイルの終端に達したり、エラーが発生した場合はfalseを返します。

サンプルコード

PHP fgetcsvのバグ回避 CSV読み込み

1<?php
2
3/**
4 * fgetcsv のバグを回避するためのサンプルコード
5 *
6 * fgetcsv は、特に長い行や不正なフォーマットの CSV ファイルを処理する際に、
7 * 予期せぬ動作をすることがあります。
8 * このサンプルコードでは、fgets と str_getcsv を組み合わせて、
9 * より堅牢な CSV ファイルの読み込みを試みます。
10 *
11 * 注意: この方法は必ずしも全ての問題を解決するわけではありません。
12 *      CSV ファイルの構造によっては、さらなる対策が必要になる場合があります。
13 */
14
15function readCSVRobustly(string $filename, string $separator = ',', string $enclosure = '"', string $escape = '\\'): array
16{
17    $rows = [];
18    $file = fopen($filename, 'r');
19
20    if ($file === false) {
21        throw new Exception("ファイルを開けませんでした: $filename");
22    }
23
24    while (!feof($file)) {
25        $line = fgets($file);
26
27        if ($line === false) {
28            break; // ファイルの終端またはエラー
29        }
30
31        // 空行をスキップ
32        $line = trim($line);
33        if ($line === '') {
34            continue;
35        }
36        
37        $data = str_getcsv($line, $separator, $enclosure, $escape);
38        $rows[] = $data;
39    }
40
41    fclose($file);
42    return $rows;
43}
44
45// 使用例:
46$filename = 'data.csv'; // CSV ファイル名
47$separator = ',';
48$enclosure = '"';
49$escape = '\\';
50
51// サンプルデータを作成 (data.csv)
52$csv_data = [
53    ['名前', '年齢', '職業'],
54    ['山田太郎', '30', 'エンジニア'],
55    ['田中花子', '25', 'デザイナー'],
56    ['佐藤健太', '40', 'マネージャー'],
57];
58
59$fp = fopen($filename, 'w');
60foreach ($csv_data as $fields) {
61    fputcsv($fp, $fields);
62}
63fclose($fp);
64
65try {
66    $data = readCSVRobustly($filename, $separator, $enclosure, $escape);
67
68    // データの表示
69    foreach ($data as $row) {
70        print_r($row);
71    }
72} catch (Exception $e) {
73    echo 'エラー: ' . $e->getMessage() . PHP_EOL;
74} finally {
75    // 作成したファイルを削除
76    unlink($filename);
77}
78?>

PHPのfgetcsv関数は、ファイルストリームから1行ずつCSV形式のデータを読み込み、配列として返します。引数には、読み込むファイルストリーム $stream、最大行の長さ $length(省略可能)、区切り文字 $separator(デフォルトはカンマ)、囲み文字 $enclosure(デフォルトはダブルクォート)、エスケープ文字 $escape(デフォルトはバックスラッシュ)を指定します。正常に読み込めた場合は配列を返し、ファイルの終端に達した場合やエラーが発生した場合は false を返します。

しかし、fgetcsv 関数は、非常に長い行や不正な形式のCSVファイルを扱う際に、予期せぬ動作をすることがあります。このサンプルコードは、fgets 関数と str_getcsv 関数を組み合わせることで、より堅牢にCSVファイルを読み込む方法を示しています。

readCSVRobustly 関数は、ファイルを開き、fgets 関数で1行ずつ読み込みます。読み込んだ行は str_getcsv 関数で解析され、配列として $rows に追加されます。空行はスキップされます。この方法により、fgetcsv 関数が抱える可能性のある問題を回避できます。ただし、この方法でも全ての問題を解決できるわけではありません。CSVファイルの構造によっては、さらなる対策が必要となる場合があります。

サンプルコードでは、data.csv という名前のサンプルCSVファイルを作成し、readCSVRobustly 関数を使用して読み込んでいます。読み込んだデータは print_r 関数で表示されます。エラーが発生した場合は、エラーメッセージが表示されます。最後に、作成したサンプルファイルを削除します。このサンプルは、システムエンジニアを目指す方が、CSVファイルを安全に読み込むためのヒントとなるでしょう。

fgetcsv関数は、CSVファイルを読み込む際に便利な関数ですが、いくつかの注意点があります。特に、長い行や不正な形式のCSVファイルを扱う際に、予期せぬ動作をする可能性があります。サンプルコードでは、fgets関数で1行ずつ読み込み、str_getcsv関数でCSV形式に分解することで、より堅牢な読み込みを試みています。ただし、この方法でも全てのケースに対応できるわけではありません。CSVファイルの構造によっては、特殊な文字のエスケープ処理や、文字コードの問題など、追加の対策が必要となる場合があります。readCSVRobustly関数の引数で区切り文字、囲み文字、エスケープ文字を指定できます。これらがCSVファイルと一致しているか確認してください。ファイルを開けなかった場合や、処理中にエラーが発生した場合の例外処理も重要です。

PHP fgetcsv でCSVを読み込む

1<?php
2
3// サンプルCSVファイル名
4$csvFileName = 'sample_data.csv';
5
6// サンプルCSVデータ(セミコロン区切り、ダブルクォート囲み)を定義します。
7// fgetcsv関数でこのファイルを読み込む際、区切り文字をセミコロンに指定する例を示します。
8$csvData = <<<CSV
9"ID";"名前";"年齢"
101;"田中";30
112;"山田";25
123;"佐藤";35
13CSV;
14
15// 1. サンプルCSVファイルをプログラムで作成します。
16// これにより、このコードをそのまま実行するだけで動作し、読み込むファイルが存在する状態になります。
17if (file_put_contents($csvFileName, $csvData) === false) {
18    echo "エラー: サンプルCSVファイルの作成に失敗しました。\n";
19    exit(1);
20}
21echo "サンプルCSVファイル '{$csvFileName}' を作成しました。\n";
22
23// 2. CSVファイルを読み込みモード ('r') で開きます。
24// fopen関数は、成功するとファイルリソース(ストリーム)を、失敗するとfalseを返します。
25$fileHandle = fopen($csvFileName, 'r');
26
27if ($fileHandle === false) {
28    echo "エラー: ファイル '{$csvFileName}' を開けませんでした。\n";
29    // ファイルが開けなかった場合でも、作成したサンプルファイルを削除します。
30    unlink($csvFileName); 
31    exit(1);
32}
33
34echo "\n--- CSVデータを読み込みます ---\n";
35
36// 3. fgetcsv関数を使ってCSVファイルから1行ずつデータを読み込みます。
37// fgetcsvの引数: resource $stream, ?int $length = null, string $separator = ',', string $enclosure = '"', string $escape = '\\'
38//   - 第1引数 ($stream): ファイルリソース(fopenで取得した$fileHandle)
39//   - 第2引数 ($length): 読み込む最大バイト数。通常はnullを指定し、PHPに自動で判断させます。
40//   - 第3引数 ($separator): 各フィールドを区切る文字。ここではセミコロン(;)を指定しています。
41//   - 第4引数 ($enclosure): フィールドを囲む文字。通常はダブルクォート(")です。デフォルト値を使用。
42//   - 第5引数 ($escape): エスケープ文字。通常はバックスラッシュ(\)です。デフォルト値を使用。
43// fgetcsvは、成功すると配列を、ファイルの終端に達するか失敗するとfalseを返します。
44while (($data = fgetcsv($fileHandle, null, ';', '"', '\\')) !== false) {
45    // 読み込んだデータを表示します。
46    // 各行が配列として取得されていることを確認できます。
47    echo "読み込んだ行: ";
48    print_r($data);
49}
50
51// 4. ファイルの使用が終わったら、fclose関数でファイルを閉じます。
52// 開いたファイルハンドルは必ず閉じるようにしましょう。
53fclose($fileHandle);
54echo "\nファイル '{$csvFileName}' の読み込みが完了しました。\n";
55
56// 5. 作成したサンプルCSVファイルを削除します(クリーンアップ)。
57if (unlink($csvFileName)) {
58    echo "サンプルCSVファイル '{$csvFileName}' を削除しました。\n";
59} else {
60    echo "エラー: サンプルCSVファイル '{$csvFileName}' の削除に失敗しました。\n";
61}
62
63?>

fgetcsv関数は、PHPでCSVファイルからデータを効率的に読み込むための機能です。このサンプルコードでは、まずプログラムでセミコロン区切り、ダブルクォート囲みのCSVファイルを作成し、そのファイルをfgetcsvを使って1行ずつ読み込む一連の処理を示しています。

fgetcsv関数は、fopen関数で開いたファイルリソース($fileHandle)を最初の引数として受け取ります。そして、ファイルから1行分のCSVデータを読み込み、各フィールドを要素とする配列として返します。読み込む最大バイト数を指定する第2引数は、通常nullを指定し、PHPに自動判断させます。特に重要なのは第3引数で、CSVファイルの各フィールドを区切る文字を指定します。今回のサンプルではセミコロン(;)で区切られているため、';'を指定しています。また、フィールドを囲む文字やエスケープ文字も引数で指定できますが、今回はデフォルト値が適用されています。

fgetcsvは、成功すると配列を返しますが、ファイルの終端に達したり読み込みに失敗したりした場合はfalseを返します。この挙動を利用して、whileループでファイルの最後までデータを順に処理し、読み込んだ行を配列として表示しています。ファイル操作の最後には、fopenで開いたファイルをfclose関数で必ず閉じるようにしましょう。fgetcsv関数は、異なる形式のCSVデータにも柔軟に対応できるため、システム開発におけるデータ連携で非常に役立つ機能です。

fgetcsv関数は、CSVファイルの区切り文字(第3引数$separator)を正確に指定しないと、期待通りにデータを読み込めませんので注意が必要です。デフォルトはカンマですが、サンプルコードのようにセミコロンを使う場合は明示的な指定が求められます。関数はファイルの終端やエラー時にfalseを返しますので、ループの終了条件として!== falseで厳密に判定し、適切に処理を終了させることが重要です。また、fopenで開いたファイルリソースは、処理完了後に必ずfcloseで閉じてリソースを解放してください。ファイル操作は失敗する可能性があるため、fopenなどの戻り値をチェックし、エラーハンドリングを丁寧に行うことで、より堅牢なプログラムになります。第2引数の$lengthは通常nullを指定し、PHPに自動判断させるのが一般的です。

PHP: fgetcsvでCSV改行コードを自動認識して読み込む

1<?php
2
3/**
4 * 指定されたCSVファイルからデータを読み込み、各行を配列として表示します。
5 * fgetcsv関数は、CSV標準の改行コード (LF, CRLFなど) を自動的に検出し、
6 * それを行の区切りとして認識してデータを読み込みます。
7 * そのため、改行コードを明示的に指定する必要はありません。
8 *
9 * @param string $filePath 読み込むCSVファイルのパス。
10 * @return void
11 */
12function readCsvAndDisplay(string $filePath): void
13{
14    // ファイルを読み込みモード ('r') で開きます。
15    // fgetcsvは内部で改行コードを自動処理するため、特別なモードは不要です。
16    $handle = fopen($filePath, 'r');
17
18    if ($handle === false) {
19        echo "エラー: ファイル '{$filePath}' を開けませんでした。\n";
20        return;
21    }
22
23    echo "--- CSVファイル '{$filePath}' の内容 ---\n";
24
25    // ファイルの終わり (EOF) まで1行ずつ読み込みます。
26    // fgetcsvは1行を読み込むごとに、内部で次の行の開始位置までポインタを進めます。
27    // このとき、行の末尾にある改行コードは読み込まれたデータには含まれません。
28    while (($data = fgetcsv($handle)) !== false) {
29        // 読み込んだ行のデータ(配列)を表示します。
30        echo "行データ: " . implode(', ', $data) . "\n";
31    }
32
33    // 開いたファイルを閉じます。リソースの解放は重要です。
34    fclose($handle);
35    echo "--- ファイル読み込み完了 ---\n";
36}
37
38// --- 単体で動作可能なサンプルコード ---
39
40// 1. 読み込むためのサンプルCSVファイルを一時的に作成します。
41$csvFileName = 'sample_data.csv';
42$csvContent = <<<CSV
43商品名,価格,在庫数
44りんご,100,50
45バナナ,150,30
46オレンジ,80,70
47CSV;
48file_put_contents($csvFileName, $csvContent);
49
50// 2. 作成したCSVファイルを読み込んで表示する関数を呼び出します。
51readCsvAndDisplay($csvFileName);
52
53// 3. 一時的に作成したCSVファイルを削除します。(任意)
54unlink($csvFileName);
55
56?>

PHPのfgetcsv関数は、CSV(Comma Separated Values)形式のファイルからデータを効率的に1行ずつ読み込むために使用されます。この関数の大きな特徴は、CSVファイルで一般的に使われるLF(Line Feed)やCRLF(Carriage Return Line Feed)など、さまざまな改行コードを自動的に検出し、それを行の区切りとして認識することです。そのため、プログラマーが改行コードを明示的に指定したり、ファイルの改行形式を意識したりする必要がなく、様々な環境で作成されたCSVファイルを安定して処理できます。

最初の引数 $stream には、fopen関数などを使って読み込みモードで開いたファイルのリソースを指定します。このリソースを通じて、fgetcsvはファイルの内容を読み取ります。オプションの引数として、読み込む行の最大長 $length や、CSVデータの区切り文字 $separator、囲み文字 $enclosure、エスケープ文字 $escape を指定できますが、これらには標準的なデフォルト値が設定されています。

関数が正常に1行を読み込むと、その行の各フィールドが要素となった配列を返します。読み込まれたデータには改行コード自体は含まれません。もしファイルの終端(EOF)に達したか、または読み込み中にエラーが発生した場合は false が返されます。サンプルコードでは、fopenで開いたファイルリソースをfgetcsvに渡し、whileループでfalseが返されるまで繰り返し呼び出すことで、CSVファイル全体の内容を読み込んでいます。これにより、CSVファイルのデータを簡単に配列として取得し、処理することが可能になります。

fgetcsv関数は、LFやCRLFといった多様な改行コードを自動的に検出し、読み込んだデータからこれらを削除してくれますので、改行コードを意識する必要はありません。ファイルを開く際はfopenで適切にリソースを取得し、処理が終わったら必ずfcloseで閉じてリソースを解放することが重要です。この関数は、ファイルの終端や読み込みエラー時にfalseを返すため、!== falseのような厳密な比較を用いて、適切にエラーや終端をハンドリングしてください。標準以外の区切り文字や囲み文字などを使用する場合は、第三引数以降を明示的に指定することで対応できます。なお、PHP 8では第二引数の$lengthは非推奨となり、設定しても無視されるためご注意ください。

PHP fgetcsv 文字化け解消 CSV読み込み

1<?php
2
3/**
4 * fgetcsv で発生しやすい文字化け問題を解決しながらCSVファイルを読み込む関数。
5 *
6 * この関数は、Shift-JISなどのUTF-8以外のエンコーディングで保存されたCSVファイルを
7 * 読み込む際に発生する文字化けを `mb_convert_encoding` を使用して解決し、
8 * UTF-8エンコーディングのデータとして返します。
9 *
10 * @param string $filePath CSVファイルのパス。
11 * @param string $fromEncoding CSVファイルの元のエンコーディング (例: 'SJIS-win', 'EUC-JP')。
12 * @param string $toEncoding 変換したいエンコーディング (通常は 'UTF-8')。
13 * @param string $separator フィールドの区切り文字 (デフォルトはカンマ)。
14 * @param string $enclosure フィールドを囲む文字 (デフォルトはダブルクォーテーション)。
15 * @param string $escape エスケープ文字 (デフォルトはバックスラッシュ)。
16 * @return array|false 読み込んだデータの配列、またはエラー時に false を返します。
17 */
18function readCsvWithEncodingConversion(
19    string $filePath,
20    string $fromEncoding = 'SJIS-win',
21    string $toEncoding = 'UTF-8',
22    string $separator = ',',
23    string $enclosure = '"',
24    string $escape = '\\'
25): array|false {
26    // ファイルが存在しない場合はエラーを報告して終了
27    if (!file_exists($filePath)) {
28        echo "エラー: ファイル '{$filePath}' が見つかりません。\n";
29        return false;
30    }
31
32    // ファイルを読み込みモードで開きます
33    $handle = fopen($filePath, 'r');
34    if ($handle === false) {
35        echo "エラー: ファイル '{$filePath}' を開けませんでした。\n";
36        return false;
37    }
38
39    $data = [];
40    // CSVファイルを1行ずつ読み込みます
41    while (($rowData = fgetcsv($handle, 0, $separator, $enclosure, $escape)) !== false) {
42        // 各行の各要素を、指定された元のエンコーディングから目的のエンコーディングに変換します。
43        // fgetcsvはバイト列としてデータを読み込むため、この変換が文字化け防止に重要です。
44        $decodedRow = array_map(function ($value) use ($fromEncoding, $toEncoding) {
45            return mb_convert_encoding($value, $toEncoding, $fromEncoding);
46        }, $rowData);
47        $data[] = $decodedRow;
48    }
49
50    // ファイルを閉じます
51    fclose($handle);
52    return $data;
53}
54
55// --- 以下は `readCsvWithEncodingConversion` 関数の利用例です ---
56
57// 1. サンプルCSVファイルを一時的に作成します。
58//    このファイルは、Shift-JIS (Windows-31J / CP932) でエンコードされています。
59//    これにより、fgetcsvでそのまま読み込むと文字化けが発生する状況をシミュレートします。
60$tempFileName = sys_get_temp_dir() . '/sample_sjis_for_fgetcsv.csv';
61$csvContent = [
62    ['商品ID', '商品名', '価格'],
63    ['1', 'りんご', '100'],
64    ['2', 'みかん', '80'],
65    ['3', 'バナナ', '120'],
66];
67
68$fileHandle = fopen($tempFileName, 'w');
69if ($fileHandle === false) {
70    echo "エラー: 一時ファイル '{$tempFileName}' の作成に失敗しました。\n";
71    exit(1);
72}
73
74// CSVファイルに書き込む前に、UTF-8の文字列をShift-JIS-winに変換します。
75// これにより、読み込む際にShift-JISとして扱えるファイルが作成されます。
76foreach ($csvContent as $row) {
77    $convertedRowForWrite = array_map(function ($value) {
78        return mb_convert_encoding($value, 'SJIS-win', 'UTF-8');
79    }, $row);
80    fputcsv($fileHandle, $convertedRowForWrite);
81}
82fclose($fileHandle);
83
84echo "一時ファイル '{$tempFileName}' (Shift-JISエンコード) を作成しました。\n\n";
85
86// 2. 作成したShift-JISのCSVファイルを読み込み、文字化けを解決します。
87echo "CSVデータを読み込み中 (Shift-JIS -> UTF-8 変換):\n";
88$decodedCsvData = readCsvWithEncodingConversion($tempFileName, 'SJIS-win', 'UTF-8');
89
90if ($decodedCsvData !== false) {
91    // 変換されたCSVデータを表示します。
92    // 各要素がUTF-8に変換されているため、正しく表示されます。
93    foreach ($decodedCsvData as $rowNumber => $row) {
94        echo "行 " . ($rowNumber + 1) . ": ";
95        print_r($row);
96    }
97} else {
98    echo "CSVファイルの読み込み中にエラーが発生しました。\n";
99}
100
101// 3. 使用した一時ファイルを削除します。
102if (file_exists($tempFileName) && unlink($tempFileName)) {
103    echo "\n一時ファイル '{$tempFileName}' を削除しました。\n";
104} else {
105    echo "\nエラー: 一時ファイル '{$tempFileName}' の削除に失敗しました、またはファイルが存在しませんでした。\n";
106}
107
108?>

fgetcsv関数は、PHPでCSVファイルを1行ずつ読み込むための関数です。$stream引数にファイルポインタを指定し、$lengthで最大文字数(省略時は行全体)、$separatorで区切り文字(デフォルトはカンマ)、$enclosureで囲み文字(デフォルトはダブルクォーテーション)、$escapeでエスケープ文字(デフォルトはバックスラッシュ)を指定できます。

このサンプルコードでは、fgetcsvを使用してCSVファイルを読み込む際に発生しやすい文字化けの問題を解決する方法を示します。特に、Shift-JISなどのUTF-8以外のエンコーディングで保存されたCSVファイルを扱う場合に有効です。

readCsvWithEncodingConversion関数は、CSVファイルのパス$filePath、元のエンコーディング$fromEncoding、変換後のエンコーディング$toEncodingを指定して呼び出します。内部でfgetcsvで読み込んだ各行のデータをmb_convert_encoding関数を使って指定されたエンコーディングに変換することで、文字化けを防ぎます。変換されたデータは配列として返されます。エラーが発生した場合はfalseを返します。この関数を利用することで、文字化けを気にせずにCSVファイルを扱うことができます。

fgetcsv関数利用時の注意点です。CSVファイルの文字コードがUTF-8でない場合、文字化けが発生します。mb_convert_encoding関数を利用して、CSVファイルのエンコーディングをUTF-8に変換することで文字化けを防ぎます。サンプルコードでは、Shift-JISのCSVファイルをUTF-8に変換しています。fopenでファイルを開く際、適切なモード(例:'r'は読み込み)を指定してください。また、fgetcsvの引数lengthは、PHP 8.1以降は非推奨です。0を指定することで、行の長さを自動で判別できます。最後に、fcloseでファイルを閉じることを忘れないようにしてください。

関連コンテンツ

関連プログラミング言語