【PHP8.x】fscanf関数の使い方

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

作成日: 更新日:

基本的な使い方

fscanf関数は、ファイルポインタから書式指定文字列に従ってデータを読み込む関数です。この関数は、指定されたファイルリソースから、特定のパターンに合致するテキストデータを抽出し、それを変数に格納する際に非常に役立ちます。例えば、ログファイルや設定ファイル、あるいはCSV形式のような構造化されたテキストファイルから、日付、数値、文字列といった特定の情報を効率的に読み取りたい場合に利用されます。

第一引数にはfopen関数などで開いたファイルポインタを、第二引数には読み込むデータの形式を指定する書式指定文字列(例:文字列は%s、整数は%dなど)を渡します。さらに、オプションとして、読み込んだ値を格納するための変数を参照渡しで追加の引数として指定することができます。これらの引数にデータが正常に割り当てられた場合、fscanf関数は割り当てられた変数の数を返します。もし、参照渡しで変数を指定しなかった場合は、パースされた値が配列として返されます。

ファイルポインタが不正であったり、読み込み中にエラーが発生したり、ファイルの終端に達してデータが読み込めなかった場合は、falseが返されます。この関数を使用することで、複雑なデータを持つテキストファイルから必要な情報を簡単に抽出・加工できるようになり、データ処理の柔軟性が高まります。

構文(syntax)

1<?php
2$handle = fopen("example.txt", "r");
3if ($handle) {
4    // example.txt から文字列、文字列、整数を読み込み、$data に配列として格納する
5    // "%s" は文字列、"%d" は整数を表すフォーマット指定子
6    $data = fscanf($handle, "%s %s %d");
7    fclose($handle);
8}
9?>

引数(parameters)

$stream, string $format, mixed ...$vars

  • resource|object $stream: 読み込み対象のストリームリソース(ファイルハンドルなど)
  • string $format: 読み込むデータのフォーマットを指定する文字列
  • mixed ...$vars: 読み込んだデータを格納するための変数を可変長引数として指定

戻り値(return)

array|int|false|null

fscanf関数は、指定されたファイルポインタからフォーマット文字列に従ってデータを読み込み、その結果を配列、または読み込んだフィールド数を整数で返します。読み込みに失敗した場合はfalseを返します。

サンプルコード

fscanf function: ファイルからCSV形式データを読み込む

1<?php
2
3/**
4 * ファイルからユーザーデータを読み込み、表示するサンプル関数。
5 * fscanf関数を使用して、指定されたフォーマットでファイルからデータを解析します。
6 * この例では、一時的なメモリファイルにサンプルデータを書き込み、そこから読み込みます。
7 */
8function readUserDataFromFile(): void
9{
10    // 一時的なメモリファイルを作成します。これにより、実際のファイルシステムに影響を与えずにテストできます。
11    // 'r+' モードは読み書きを可能にし、ファイルが存在しない場合は作成を試みます。
12    $tempFile = fopen('php://memory', 'r+');
13    if (!$tempFile) {
14        echo "エラー: 一時ファイルの作成に失敗しました。\n";
15        return;
16    }
17
18    // サンプルデータを一時ファイルに書き込みます。
19    // 各行は「名前,年齢,身長」のCSV形式です。
20    fwrite($tempFile, "Alice,30,165.5\n");
21    fwrite($tempFile, "Bob,25,178.0\n");
22    fwrite($tempFile, "Charlie,35,170.2\n");
23    fwrite($tempFile, "David,40,180.0\n");
24
25    // ファイルポインタをファイルの先頭に戻します。
26    // これにより、書き込んだデータがfscanfで読み込み可能になります。
27    fseek($tempFile, 0);
28
29    echo "ファイルからユーザーデータを読み込み、解析します。\n";
30    echo "---------------------------------------------------\n";
31
32    // fscanf用のフォーマット文字列を定義します。
33    // %[^,] : カンマ以外の文字を読み込みます (名前)
34    // %d    : 整数を読み込みます (年齢)
35    // %f    : 浮動小数点数を読み込みます (身長)
36    $format = "%[^,],%d,%f";
37
38    // ファイルの終わり(EOF)に達するか、fscanfがfalse(エラー)またはnull(EOF)を返すまでループします。
39    while (($userData = fscanf($tempFile, $format)) !== false && $userData !== null) {
40        // fscanfが成功した場合、読み込んだデータは配列として返されます。
41        // 配列の要素数が期待通りか確認します。
42        if (is_array($userData) && count($userData) === 3) {
43            echo "名前: " . $userData[0] . ", ";
44            echo "年齢: " . $userData[1] . ", ";
45            echo "身長: " . $userData[2] . "\n";
46        } else {
47            // フォーマットに一致しない行があった場合の処理
48            echo "警告: フォーマットに一致しないデータが見つかりました。\n";
49        }
50    }
51
52    // 開いたファイルを閉じます。
53    fclose($tempFile);
54
55    echo "---------------------------------------------------\n";
56    echo "データの読み込みが完了しました。\n";
57}
58
59// 関数を実行します。
60readUserDataFromFile();
61
62?>

PHPのfscanf関数は、ファイルから指定した書式(フォーマット)に従ってデータを読み込むための関数です。このサンプルコードでは、メモリ上に作成した一時ファイルから、CSV形式のユーザーデータを1行ずつ解析しています。

第1引数にはfopen関数などで開いたファイルポインタを渡し、どのファイルからデータを読み込むかを指定します。第2引数には、データの書式を定義する文字列を指定します。この例の"%[^,],%d,%f"という書式は、「カンマ以外の文字列」「整数」「浮動小数点数」がこの順でカンマ区切りになっているデータ行を読み込むことを意味します。

PHP 8.0以降、fscanf関数は読み込みに成功すると、取得した値を格納した配列を返します。サンプルでは、この配列を受け取って各データを表示しています。ファイルの終端に達するとnullを、エラーの場合はfalseを返すため、whileループと組み合わせることでファイルの最後まで安全にデータを読み進めることができます。このように、fscanf関数は特定の構造を持つテキストファイルからデータを効率的に抽出する際に役立ちます。

fscanf関数は、第二引数で指定するフォーマット文字列が非常に重要です。特に%[^,]は「カンマ以外の文字」を読み込む特殊な指定で、データの形式と完全に一致していないと正しく解析できません。関数の戻り値は、成功時に配列、入力が尽きた場合にnull、エラー時にfalseを返します。そのため、ループを安全に実行するには、サンプルコードのようにnullfalseの両方を厳密にチェックする必要があります。また、ファイルに書き込み後、読み込みを開始する前にはfseekでファイルポインタを先頭に戻す操作が不可欠です。最後に、fopenで開いたリソースは、処理完了後に必ずfcloseで閉じてください。

PHP fscanfで標準入力を読み取る

1<?php
2
3declare(strict_types=1);
4
5/**
6 * 標準入力(STDIN)から fscanf を使用してデータを読み取るサンプルです。
7 *
8 * このスクリプトをコマンドラインで実行し、
9 * 名前と年齢をスペースで区切って入力してからEnterキーを押してください。
10 * (例: Taro 25)
11 */
12function readFormattedInputFromStdin(): void
13{
14    // ユーザーに入力を促すメッセージを表示します。
15    echo "名前と年齢をスペース区切りで入力してください (例: Taro 25): ";
16
17    // 変数を初期化します。
18    $name = null;
19    $age = null;
20
21    // 標準入力ストリーム(STDIN)からフォーマット指定でデータを読み取ります。
22    // "%s %d" は「文字列、スペース、整数」という形式を示します。
23    // 読み取られた値は、第3引数以降で渡した変数に格納されます。
24    $assignedCount = fscanf(STDIN, "%s %d", $name, $age);
25
26    // fscanfは正常に読み込み、変数に代入できた項目の数を返します。
27    // 今回は名前と年齢の2項目が読み込めることを期待しています。
28    if ($assignedCount === 2) {
29        // 読み取ったデータを使用してメッセージを出力します。
30        printf("こんにちは、%sさん! あなたは%d歳ですね。\n", $name, $age);
31    } else {
32        // 入力が期待したフォーマットと異なっていた場合のエラーメッセージです。
33        fwrite(STDERR, "エラー: 入力形式が正しくありません。\n");
34    }
35}
36
37// 関数を実行します。
38readFormattedInputFromStdin();

fscanf関数は、ファイルポインタや標準入力などのストリームから、指定した書式(フォーマット)に従ってデータを読み取るための関数です。このサンプルコードは、コマンドラインでユーザーがキーボードから入力した名前と年齢をfscanf関数を使って受け取る処理を示しています。

fscanf関数の第1引数には、データの読み取り元となるストリームを指定します。ここではSTDINが指定されており、これは「標準入力」、つまりキーボードからの入力を意味します。

第2引数の"%s %d"は、入力データの書式を指定する文字列です。%sは任意の文字列、%dは10進数の整数を表しており、「文字列、スペース、整数」という形式のデータを期待していることを示します。

第3引数以降には、読み取ったデータを格納するための変数を指定します。サンプルでは、書式%sで読み取った文字列が変数$nameに、%dで読み取った整数が変数$ageにそれぞれ代入されます。

この関数の戻り値は、書式に従って正常に読み込み、変数に代入できた項目の数です。サンプルでは、名前と年齢の2項目が正しく代入されることを期待しているため、戻り値が2であるかどうかを確認し、入力が正しい形式であったかを判断しています。もし入力が期待した形式でなかった場合、戻り値は2未満となり、エラーメッセージが表示されます。

fscanf関数を使う際の注意点を説明します。この関数は第3引数以降に渡した変数へ直接値を代入するため、事前に変数を定義しておく必要があります。ユーザーの入力は常に正しいとは限らないため、関数の戻り値を確認することが非常に重要です。戻り値は正常に代入できた項目の数なので、この値が期待通りかチェックすることで、不正な形式の入力によるエラーを防げます。また、フォーマット指定子"%s"は空白文字までの文字列しか読み込みません。そのため、名前にスペースが含まれる場合(例: "Taro Yamada")は期待通りに動作しない点にも注意してください。このような場合は一行ずつ読み込むfgetsなどの利用を検討すると良いでしょう。

関連コンテンツ

【PHP8.x】fscanf関数の使い方 | いっしー@Webエンジニア