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

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

作成日: 更新日:

基本的な使い方

fseek関数は、ファイルポインタを移動させる関数です。PHPでファイルを開いて読み書きを行う際、ファイル内には現在の読み書き位置を示す「ファイルポインタ」という内部的な目印があります。fseek関数は、このファイルポインタを指定した位置に移動させるために使用されます。

この関数を利用することで、開いているファイルの特定のバイト位置に直接ジャンプし、そこからデータの読み書きを開始することが可能になります。例えば、ファイルの先頭から何バイト目かの位置に移動したり、現在の読み書き位置から前後に指定したバイト数だけ移動したり、あるいはファイルの末尾に移動したりすることができます。これにより、ファイル全体を順に読み進めるだけでなく、必要な部分だけを効率的に読み書きできるようになります。

fseek関数は主に3つの引数を取ります。1つ目はfopen()などで取得したファイルリソース、2つ目は移動するバイト数を示す「オフセット」、3つ目はオフセットの基準位置です。基準位置には、ファイルの先頭からの移動を示すSEEK_SET、現在のファイルポインタ位置からの移動を示すSEEK_CUR、ファイルの末尾からの移動を示すSEEK_ENDのいずれかを指定します。

移動が成功した場合は0を返し、失敗した場合は-1を返しますので、関数の戻り値を確認することで、ファイルポインタの移動が適切に行われたかを判断できます。この機能は、特に大きなファイルを扱う場合や、ファイル内の特定のデータブロックに素早くアクセスする必要がある場合に非常に有効です。ファイルの特定箇所に繰り返しアクセスするような処理で、効率的なファイル操作を実現します。

構文(syntax)

1<?php
2$fileResource = fopen('data.txt', 'r');
3$byteOffset = 10;
4$seekOrigin = SEEK_SET; // SEEK_SET (ファイル先頭), SEEK_CUR (現在位置), SEEK_END (ファイル末尾)
5
6$status = fseek($fileResource, $byteOffset, $seekOrigin);
7
8fclose($fileResource);
9?>

引数(parameters)

resource $stream, int $offset, int $whence = SEEK_SET

  • resource $stream: 操作対象のファイルポインタまたはストリームリソース
  • int $offset: 移動するバイト数
  • int $whence = SEEK_SET: 相対位置を指定する定数 (SEEK_SET: ファイルの先頭, SEEK_CUR: 現在位置, SEEK_END: ファイルの末尾)

戻り値(return)

int

ファイルポインタを移動させた位置をバイト単位で返します。成功した場合は0、失敗した場合は-1を返します。

サンプルコード

PHP fseekでファイル終端へ移動

1<?php
2
3/**
4 * PHPのfseek()関数を使い、ファイルポインタをファイルの終端に移動させる例。
5 * SEEK_END定数を使用し、ファイルサイズを取得する一般的なシナリオを示します。
6 * システムエンジニアを目指す初心者がファイル操作の基本を理解するのに役立ちます。
7 */
8function demonstrateFseekToEndOfFile(): void
9{
10    $filename = 'fseek_example.txt';
11    $content = "Hello, PHP!\nThis is a test file for fseek with SEEK_END.\n";
12
13    // 1. テストファイルを作成し、内容を書き込む
14    // file_put_contents() は、指定したファイルにデータを書き込みます。
15    file_put_contents($filename, $content);
16    echo "ファイル '{$filename}' を作成しました。内容: " . mb_strlen($content, '8bit') . "バイト\n";
17
18    // 2. ファイルを読み書きモードで開く
19    // 'r+' モードは、既存ファイルを読み書きモードで開きます。ファイルポインタはファイルの先頭に位置します。
20    $fileHandle = fopen($filename, 'r+');
21
22    if ($fileHandle === false) {
23        echo "エラー: ファイル '{$filename}' のオープンに失敗しました。\n";
24        return;
25    }
26
27    echo "ファイルを開きました。\n";
28
29    // 3. fseek() を使ってファイルポインタをファイルの終端に移動
30    // 第1引数: 操作するファイルリソース
31    // 第2引数: オフセット (基準点から0バイトの位置)
32    // 第3引数: 基準点 (SEEK_END: ファイルの終端を基準とする)
33    $seekResult = fseek($fileHandle, 0, SEEK_END);
34
35    if ($seekResult === 0) { // fseek() は成功すると0を返します
36        echo "ファイルポインタを終端に移動しました。\n";
37
38        // 4. ftell() で現在のファイルポインタの位置を取得
39        // ファイルの終端にいる場合、この値はファイルのバイトサイズと等しくなります。
40        $fileSize = ftell($fileHandle);
41        echo "現在のファイルポインタの位置 (ファイルサイズ): {$fileSize}バイト\n";
42
43    } else {
44        echo "エラー: ファイルポインタの移動に失敗しました。\n";
45    }
46
47    // 5. ファイルリソースを閉じる
48    // ファイル操作の終了時には必ずファイルを閉じることが重要です。
49    fclose($fileHandle);
50    echo "ファイルを閉じました。\n";
51
52    // 6. テストファイルを削除してクリーンアップ
53    unlink($filename);
54    echo "ファイル '{$filename}' を削除しました。\n";
55}
56
57// 関数を実行
58demonstrateFseekToEndOfFile();

PHPのfseek関数は、ファイルを開いた際にデータへアクセスするための「ファイルポインタ」の位置を移動させるために使用します。このサンプルコードは、まずテキストファイルを作成し、それを読み書きモードで開いた後、fseek関数を使ってファイルポインタをファイルの終端へ移動させ、ファイルのサイズを取得する一般的な手順を示しています。

fseek関数は、第一引数に操作するファイルリソース(fopenで開いたファイルの識別子)、第二引数に基準点からのオフセット(移動するバイト数)、第三引数に基準点(SEK_SETでファイルの先頭、SEEK_CURで現在位置、SEEK_ENDでファイルの終端)を指定します。この例では、SEEK_ENDを基準にオフセット0を指定することで、ファイルポインタがファイルのまさに終端に移動します。

関数の戻り値は整数で、成功した場合は0を、失敗した場合は-1を返します。ファイルポインタを終端に移動させた後、ftell関数を使用すると、現在のファイルポインタの位置、すなわちファイルのバイトサイズを取得できます。ファイル操作の完了時には、fcloseでファイルリソースを閉じることを忘れないようにしましょう。

PHPのfseek関数でファイルポインタを移動させる際は、戻り値が0であれば成功、-1であれば失敗を示すため、必ず確認してエラー処理を組み込みましょう。SEEK_ENDを使用しファイル終端へ移動する場合は、オフセットを0とします。終端に移動後、ftell関数を使えばファイルのバイトサイズを取得でき、これはファイルサイズ取得の一般的な方法の一つです。fopenで開いたファイルリソースは、処理終了後にfcloseで必ず閉じることが重要です。閉じ忘れるとリソースリークの原因となりますので注意してください。

PHP fseekでファイルポインタを操作する

1<?php
2
3/**
4 * Demonstrates the use of fseek() to manipulate the file pointer's position.
5 * This example focuses on how fseek() can be used in scenarios involving
6 * reading file content line by line, including resetting the read position
7 * and attempting to jump to specific byte offsets that might correspond to lines.
8 *
9 * While fseek() operates on byte offsets, it is fundamental for controlling
10 * where in a file subsequent read operations (like fgets() for lines) will start.
11 * To directly jump to a specific line number, one would typically need to
12 * pre-calculate the byte offset of that line.
13 */
14function demonstrateFseekForLines(): void
15{
16    $filename = 'sample_lines.txt';
17    $fileContent = "Line 1: Hello PHP!\nLine 2: This is a sample file.\nLine 3: We are demonstrating fseek.\nLine 4: End of file.";
18
19    // 1. Create a dummy file for demonstration purposes.
20    file_put_contents($filename, $fileContent);
21    echo "Created file: '$filename'\n\n";
22
23    // 2. Open the file for reading.
24    $filePointer = fopen($filename, 'r');
25
26    if (!$filePointer) {
27        echo "Error: Could not open file '$filename'.\n";
28        return;
29    }
30
31    echo "--- Initial Reading ---\n";
32    // Read the first two lines. The file pointer moves forward with each read.
33    echo "  " . fgets($filePointer); // Reads "Line 1: Hello PHP!\n"
34    echo "  " . fgets($filePointer); // Reads "Line 2: This is a sample file.\n"
35
36    // Get and display the current position of the file pointer.
37    $currentPosition = ftell($filePointer);
38    echo "  Current file pointer position after reading 2 lines: " . $currentPosition . " bytes.\n\n";
39
40    // 3. Use fseek() to move the pointer back to the very beginning of the file (offset 0).
41    // SEEK_SET means the offset is relative to the beginning of the file.
42    echo "--- Seeking Back to Beginning ---\n";
43    echo "Seeking back to the beginning of the file (offset 0)...\n";
44    $seekResult = fseek($filePointer, 0, SEEK_SET);
45
46    if ($seekResult === 0) { // fseek() returns 0 on success, -1 on failure.
47        echo "  Successfully moved pointer to offset 0.\n\n";
48
49        echo "--- Re-reading from the Beginning ---\n";
50        // Now, we can read the lines again from the start.
51        echo "  " . fgets($filePointer); // Reads "Line 1: Hello PHP!\n" again
52        echo "  " . fgets($filePointer); // Reads "Line 2: This is a sample file.\n" again
53        echo "  " . fgets($filePointer); // Reads "Line 3: We are demonstrating fseek.\n"
54
55        $currentPosition = ftell($filePointer);
56        echo "  Current file pointer position after re-reading 3 lines: " . $currentPosition . " bytes.\n\n";
57
58        // 4. Demonstrate seeking to a specific byte offset.
59        // To jump to a specific "line number" directly with fseek(), you first need
60        // to know its exact byte offset. This usually involves parsing the file
61        // once to build an index of line start offsets.
62        // For demonstration, let's manually calculate an approximate offset for Line 3.
63        // "Line 1: Hello PHP!\n" is 19 bytes.
64        // "Line 2: This is a sample file.\n" is 30 bytes.
65        // So, Line 3 starts after 19 + 30 = 49 bytes.
66        $approxOffsetForLine3Start = 19 + 30; 
67
68        echo "--- Seeking to a Specific Byte Offset (Approx. Line 3) ---\n";
69        echo "Attempting to seek to an approximate start of Line 3 (offset $approxOffsetForLine3Start bytes)...\n";
70        fseek($filePointer, $approxOffsetForLine3Start, SEEK_SET);
71        // After seeking, the next read operation will start from this byte offset.
72        echo "  " . fgets($filePointer); // This should read "Line 3: We are demonstrating fseek.\n" again.
73
74        $currentPosition = ftell($filePointer);
75        echo "  Current file pointer position after seeking to approx. Line 3 and reading: " . $currentPosition . " bytes.\n\n";
76
77    } else {
78        echo "Error: Could not seek to beginning of file.\n";
79    }
80
81    // 5. Close the file resource.
82    fclose($filePointer);
83    echo "Closed file: '$filename'\n";
84
85    // 6. Clean up the dummy file created for the example.
86    unlink($filename);
87    echo "Deleted file: '$filename'\n";
88}
89
90// Execute the demonstration function.
91demonstrateFseekForLines();

PHP 8のfseek関数は、ファイル内の読み書き位置を示す「ファイルポインタ」を操作します。引数には、fopenなどで開いたファイルリソース($stream)、移動するバイト数($offset)、移動の基準点($whence)を指定します。$whenceのデフォルトはSEEK_SETでファイルの先頭からの絶対位置を指定し、SEEK_CURは現在位置から、SEEK_ENDは末尾からの相対位置です。関数は、ファイルポインタの移動が成功時に整数0を、失敗時に整数-1を返します。

サンプルコードでは、一時ファイル作成後、fgetsで読み進めたポインタをfseek($filePointer, 0, SEEK_SET)でファイルの先頭に戻し、先頭からの再読み込みを実演します。また、特定のバイトオフセットへ移動し、そこから読み込みを再開する例も紹介しています。fseekはバイト単位で動作するため、特定の行番号へ直接移動するには、その行の正確な開始バイトオフセットを事前に計算する必要があります。この機能は、ファイル中の任意の位置からデータを効率的に読み込む際に役立ちます。

fseek関数は、ファイルポインタをバイト単位で移動させるために使用します。特定の行番号へ直接移動する機能はなく、目的の行の開始バイトオフセットを事前に計算するか、ファイルの内容を解析して把握する必要があります。オフセットの基準点として、ファイルの先頭からの相対位置(SEEK_SET)、現在位置からの相対位置(SEEK_CUR)、ファイルの末尾からの相対位置(SEEK_END)を指定できますので、状況に応じて適切に選択してください。関数が成功した場合は0、失敗した場合は-1が返されるため、必ず戻り値を確認し、エラー処理を実装することが重要です。また、fopenで開いたファイルリソースは、処理が完了したら必ずfcloseで閉じるようにしてください。各行のバイト数には改行コードも含まれる点にもご注意ください。

関連コンテンツ

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