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

【PHP8.x】SplFileObject::fseek()メソッドの使い方

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

作成日: 更新日:

基本的な使い方

fseekメソッドは、PHPのSplFileObjectクラスのインスタンスが操作しているファイルの読み書き位置を示すファイルポインタを移動させるメソッドです。ファイルポインタとは、ファイル内で次にデータが読み込まれる、または書き込まれる場所を示す目印のようなものです。

このメソッドを使用すると、ファイルの特定のバイト位置へファイルポインタを正確に移動させることができます。移動の基準とオフセットを指定するために、主に二つの引数を受け取ります。最初の引数offsetには、移動させたいバイト数を整数で指定します。正の数を指定するとファイルの末尾方向へ、負の数を指定するとファイルの先頭方向へポインタが移動します。二番目の引数whenceには、ファイルポインタの移動基準を指定します。SEEK_SETを指定するとファイルの先頭からoffsetバイト、SEEK_CURを指定すると現在のポインタ位置からoffsetバイト、SEEK_ENDを指定するとファイルの末尾からoffsetバイト(通常は負の値でファイルの先頭方向へ)移動します。

例えば、ファイルの途中から読み込みを再開したい場合や、特定の部分をスキップしたい場合などに利用されます。このメソッドの実行に成功すると0を、失敗した場合は-1を返します。これにより、ファイル操作の柔軟性が大幅に向上し、効率的なデータ処理が可能になります。

構文(syntax)

1<?php
2
3$file = new SplFileObject('example.txt');
4$file->fseek(10, SEEK_SET);
5
6?>

引数(parameters)

int $offset, int $whence = SEEK_SET

  • int $offset: ファイルポインタを移動させるオフセット値を指定する整数
  • int $whence = SEEK_SET: ファイルポインタの基準位置を指定する定数 (SEEK_SET: ファイルの先頭, SEEK_CUR: 現在位置, SEEK_END: ファイルの末尾)

戻り値(return)

int

指定された位置にファイルポインタを移動させ、成功した場合は 0、失敗した場合は -1 を返します。

サンプルコード

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

1<?php
2
3/**
4 * SplFileObject::fseek の基本的な使い方をデモンストレーションする関数。
5 *
6 * この関数は、一時ファイルを作成し、内容を書き込みます。
7 * その後、SplFileObject を使用してファイルを開き、fseek メソッドを使って
8 * ファイルポインタを移動させ、その位置からデータを読み取る方法を示します。
9 * fseek は、ファイルの特定の位置から読み書きを開始したい場合に非常に役立ちます。
10 */
11function demonstrateSplFileObjectFseek(): void
12{
13    // デモンストレーション用の一時ファイル名
14    $fileName = 'fseek_example.txt';
15    // ファイルに書き込む内容
16    $fileContent = "Hello, world! This is a test file for fseek example.";
17
18    // 1. 一時ファイルを作成し、内容を書き込む
19    file_put_contents($fileName, $fileContent);
20    echo "一時ファイルを作成しました: '{$fileName}'\n";
21    echo "ファイル内容: '{$fileContent}'\n\n";
22
23    try {
24        // 2. SplFileObject を使用してファイルを開く
25        // 'r+' モードは読み書きを許可し、ファイルポインタはファイルの先頭に設定されます。
26        $file = new SplFileObject($fileName, 'r+');
27
28        echo "初期ファイルポインタ位置: " . $file->ftell() . " (ファイルの先頭)\n";
29
30        // --- fseek と SEEK_SET のデモンストレーション ---
31        // ファイルの先頭から7バイト目に移動 (0-indexed なので "Hello, " の次)
32        $offsetFromStart = 7;
33        // fseek は成功時に 0、失敗時に -1 を返します。
34        $seekResult = $file->fseek($offsetFromStart, SEEK_SET);
35
36        if ($seekResult === 0) {
37            echo "\nファイルの先頭から {$offsetFromStart} バイト目に移動しました (SEEK_SET)。\n";
38            echo "現在のファイルポインタ位置: " . $file->ftell() . "\n";
39            // 現在のポインタ位置から5バイト読み取る
40            $data = $file->fread(5); // "world" を読み取ります
41            echo "読み取ったデータ (5バイト): '{$data}'\n";
42            echo "読み取り後のポインタ位置: " . $file->ftell() . "\n";
43        } else {
44            echo "SEEK_SET でのシークに失敗しました。\n";
45        }
46
47        // --- fseek と SEEK_END のデモンストレーション ---
48        // ファイルの末尾から10バイト前に移動
49        // (負のオフセットは末尾から数えることを意味します)
50        $offsetFromEnd = -10;
51        $seekResult = $file->fseek($offsetFromEnd, SEEK_END);
52
53        if ($seekResult === 0) {
54            echo "\nファイルの末尾から {$offsetFromEnd} バイト前に移動しました (SEEK_END)。\n";
55            echo "現在のファイルポインタ位置: " . $file->ftell() . "\n";
56            // 現在のポインタ位置から残りのデータを読み取る (最大20バイト)
57            $data = $file->fread(20); // "fseek example." を読み取ります
58            echo "読み取ったデータ (最大20バイト): '{$data}'\n";
59            echo "読み取り後のポインタ位置: " . $file->ftell() . " (ファイルの終端)\n";
60        } else {
61            echo "SEEK_END でのシークに失敗しました。\n";
62        }
63
64        // --- fseek と SEEK_CUR のデモンストレーション ---
65        // ポインタをファイルの先頭に戻す
66        $file->rewind(); // または $file->fseek(0, SEEK_SET);
67        echo "\nファイルポインタを先頭に戻しました。\n";
68        echo "現在のファイルポインタ位置: " . $file->ftell() . "\n";
69
70        // 現在のポインタ位置から10バイト先に移動
71        $offsetFromCurrent = 10;
72        $seekResult = $file->fseek($offsetFromCurrent, SEEK_CUR);
73
74        if ($seekResult === 0) {
75            echo "現在の位置から {$offsetFromCurrent} バイト先に移動しました (SEEK_CUR)。\n";
76            echo "現在のファイルポインタ位置: " . $file->ftell() . "\n";
77            // 現在のポインタ位置から5バイト読み取る
78            $data = $file->fread(5); // "d! Th" を読み取ります (元のファイル内容の10文字目から)
79            echo "読み取ったデータ (5バイト): '{$data}'\n";
80            echo "読み取り後のポインタ位置: " . $file->ftell() . "\n";
81        } else {
82            echo "SEEK_CUR でのシークに失敗しました。\n";
83        }
84
85    } catch (RuntimeException $e) {
86        // SplFileObject の操作中にエラーが発生した場合
87        echo "エラーが発生しました: " . $e->getMessage() . "\n";
88    } finally {
89        // 3. デモンストレーション用ファイルをクリーンアップ
90        if (file_exists($fileName)) {
91            unlink($fileName);
92            echo "\n一時ファイルを削除しました: '{$fileName}'\n";
93        }
94    }
95}
96
97// 関数を実行してデモンストレーションを開始
98demonstrateSplFileObjectFseek();

PHP 8のSplFileObject::fseekメソッドは、ファイル内の読み書きを行う位置、すなわちファイルポインタを移動させるために使用します。この機能は、ファイルの特定の部分からデータを読み込んだり書き込んだりしたい場合に大変役立ちます。

このメソッドは二つの引数を取ります。一つ目の$offsetは、移動させるバイト数を指定します。二つ目の$whenceは、どの位置を基準に移動するかを指定する定数です。SEEK_SETはファイルの先頭を基準とし、SEEK_ENDはファイルの末尾を基準とし、SEEK_CURは現在のファイルポインタ位置を基準とします。$whenceを省略した場合はSEEK_SETが適用されます。通常、SEEK_ENDを使用する際は$offsetに負の値を指定して末尾から前方へ移動します。

fseekの呼び出しが成功した場合は0を、失敗した場合は-1を返します。

サンプルコードでは、まず一時ファイルを作成し、その内容をSplFileObjectで開いています。その後、fseekメソッドを用いてファイルポインタを移動させ、freadメソッドでその位置からデータを読み取る様子をデモンストレーションしています。具体的には、SEEK_SETでファイルの先頭から、SEEK_ENDでファイルの末尾から、SEEK_CURで現在の位置からそれぞれ指定したバイト数だけファイルポインタを移動させ、目的のデータを取り出す流れが示されており、ファイルの柔軟な操作に欠かせない機能です。

SplFileObject::fseekは、ファイル内の読み書き位置(ファイルポインタ)を移動させるために使います。$offsetで移動するバイト数を指定し、$whenceでファイルの先頭、末尾、現在位置のいずれを基準にするかを指定します。特に末尾から移動する際は負の$offsetとSEEK_ENDを使います。このメソッドは成功時に0、失敗時に-1を返しますので、必ず戻り値を確認し、エラー処理を適切に行ってください。ファイルを開く際のモードが読み書きを許可しているかも重要です。また、マルチバイト文字を含むファイルを扱う場合、文字数とバイト数が異なるため、オフセットの計算には十分注意が必要です。

SplFileObject::fseek() でファイルの末尾から読み取る

1<?php
2
3/**
4 * SplFileObject::fseek() メソッドを使用して、ファイルの末尾から指定したバイト数を読み込む方法を示します。
5 *
6 * システムエンジニアを目指す初心者向けに、ファイルの末尾を基準としたシークの基本を説明します。
7 */
8function demonstrateSplFileObjectFseekEndOfFile(): void
9{
10    $filename = 'fseek_end_example.txt';
11    // テスト用のファイル内容。UTF-8で記述されており、日本語文字は複数バイトとして扱われます。
12    $content = "これはSplFileObject::fseek()のデモンストレーション用のテストファイルです。\n";
13    $content .= "このファイルの末尾から数バイトを読み取ることで、fseek()の使用方法を理解します。\n";
14    $content .= "最終行: ファイルの末尾を基準にシークし、内容を読み取ります。";
15
16    // 一時ファイルに内容を書き込みます。
17    // file_put_contents() は、指定された文字列をそのままバイト列としてファイルに書き込みます。
18    file_put_contents($filename, $content);
19
20    try {
21        // SplFileObject を読み取りモード ('r') で開きます。
22        $file = new SplFileObject($filename, 'r');
23
24        echo "=== ファイルの末尾から内容を読み取る例 ===\n";
25        // ファイルの全体のバイト数を取得します。
26        // filesize() は、指定されたファイルのサイズをバイト単位で返します。
27        $fileSize = filesize($filename);
28        echo "元のファイル内容のバイト数 (filesize()): " . $fileSize . " バイト\n";
29
30        // 読み取りたい「最終行」の文字列。
31        $lastLine = "最終行: ファイルの末尾を基準にシークし、内容を読み取ります。";
32        // 読み取りたいバイト数を指定します。
33        // strlen() は文字列のバイト数を返します(マルチバイト文字も正しくバイト数でカウントされます)。
34        $bytesToRead = strlen($lastLine);
35
36        echo "読み取る対象の文字列 ('{$lastLine}') のバイト数: " . $bytesToRead . " バイト\n";
37
38        // fseek() を使用して、ファイルポインタをファイルの末尾から $bytesToRead バイト手前に移動させます。
39        // 第1引数 ($offset): 移動するバイト数を指定します。負の値を指定すると「後ろから前へ」移動します。
40        // 第2引数 ($whence): 基準点を指定します。SEEK_END を指定するとファイルの末尾が基準点となります。
41        // fseek() は成功すると 0 を返します。失敗した場合は -1 を返します。
42        $seekResult = $file->fseek(-$bytesToRead, SEEK_END);
43
44        if ($seekResult === 0) {
45            echo "ファイルポインタを末尾から " . $bytesToRead . " バイト前に移動しました。\n";
46            // ftell() は現在のファイルポインタの位置をバイト単位で返します。
47            echo "現在のファイルポインタ位置: " . $file->ftell() . " バイト目\n";
48
49            // 移動した位置から指定されたバイト数を読み取ります。
50            // fread() はファイルポインタの現在位置から指定バイト数だけ読み込み、その内容を文字列として返します。
51            $readContent = $file->fread($bytesToRead);
52
53            echo "読み取った内容:\n";
54            echo "--------------------------------------------------------\n";
55            echo $readContent . "\n";
56            echo "--------------------------------------------------------\n";
57        } else {
58            echo "エラー: fseek() が失敗しました。戻り値: " . $seekResult . "\n";
59        }
60
61    } catch (RuntimeException $e) {
62        // SplFileObject の操作中に発生する可能性のある例外(ファイルオープン失敗など)を捕捉します。
63        echo "エラーが発生しました: " . $e->getMessage() . "\n";
64    } finally {
65        // 使用した一時ファイルを確実に削除します。
66        // これにより、スクリプト実行後に不要なファイルが残りません。
67        if (file_exists($filename)) {
68            unlink($filename);
69            echo "\n一時ファイル '{$filename}' を削除しました。\n";
70        }
71    }
72}
73
74// デモンストレーション関数を実行します。
75demonstrateSplFileObjectFseekEndOfFile();
76

PHPのSplFileObject::fseek()メソッドは、ファイル内の読み書き位置を示す「ファイルポインタ」を、指定した場所へ移動させるための機能です。このサンプルコードでは、ファイルの「末尾」を基準としてファイルポインタを移動させ、特定の内容を読み取る方法を示しています。

まず、テスト用のファイルを作成し、SplFileObjectで読み込み用に開きます。次にfseek()メソッドを呼び出す際、第一引数$offsetには移動させたいバイト数を負の値で指定します。これは「ファイルの末尾から前方へ」移動することを意味します。第二引数$whenceにはSEEK_ENDを指定することで、ファイルの「末尾」が移動の基準点となります。例えば、-100SEEK_ENDを指定すると、ファイルポインタはファイルの末尾から100バイト手前に移動します。

fseek()メソッドは、ファイルポインタの移動に成功した場合は整数値0を、失敗した場合は-1を戻り値として返します。移動が成功した後、fread()などのメソッドを使用すれば、ファイルポインタが移動した位置からデータを読み取ることができます。この機能は、ログファイルの最新部分を効率的に取得したり、ファイルの末尾にある特定の情報を読み出したりする際に役立ちます。

SplFileObject::fseekメソッドは、ファイルの読み取り位置をバイト単位で指定します。SEEK_ENDを基準に末尾から手前へ移動する際は、オフセットに必ず負の値を指定してください。日本語などのマルチバイト文字を含むファイルを扱う場合、strlen()で取得されるのは文字数ではなくバイト数であるため、期待通りの位置へ移動するには、正確なバイト数の把握が不可欠です。fseekは成功時に0を返しますので、この戻り値で処理の成否を確認しましょう。また、ファイル操作後は、一時ファイルが残らないようfinallyブロックなどで確実に削除する習慣をつけることが重要です。

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

1<?php
2
3/**
4 * SplFileObject::fseek の使用例。
5 * ファイルを読み進めた後、ファイルポインタを以前の位置に戻して再読み込みするシナリオを示します。
6 * fseek メソッドはバイトオフセットでファイルポインタを移動させるため、行番号を直接指定することはできません。
7 * しかし、ftell と組み合わせることで、特定の行を処理した後の位置を記憶し、後でその位置に戻ることが可能になります。
8 */
9
10// 一時的なファイルを作成し、サンプルデータを書き込む
11$filePath = 'sample_fseek_line_file.txt';
12$fileContent = <<<EOT
13Line 1: The quick brown fox jumps over the lazy dog.
14Line 2: Lorem ipsum dolor sit amet, consectetur adipiscing elit.
15Line 3: Sed do eiusmod tempor incididunt ut labore et dolore magna aliqua.
16Line 4: Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris.
17Line 5: Nisi ut aliquip ex ea commodo consequat.
18EOT;
19
20// ファイルに内容を書き込む
21file_put_contents($filePath, $fileContent);
22
23echo "--- サンプルファイルの初期内容 ---\n";
24echo file_get_contents($filePath) . "\n";
25echo "----------------------------------\n\n";
26
27try {
28    // SplFileObject を読み取りモードで開く
29    // r は読み取り専用モードを意味します
30    $file = new SplFileObject($filePath, 'r');
31
32    echo "ファイルポインタの初期位置: " . $file->ftell() . " バイト (ファイルの先頭)\n\n";
33
34    // 最初の2行を読み込む
35    echo "--- 最初の2行を読み込み中 ---\n";
36    $lineNumber = 1;
37    while (!$file->eof() && $lineNumber <= 2) {
38        $line = $file->fgets(); // 1行読み込む
39        echo "読み込んだ行 {$lineNumber}: " . trim($line) . "\n";
40        $lineNumber++;
41    }
42    // fgets() の後、ファイルポインタは読み込んだ行の末尾の次の位置に移動します
43    echo "2行読み込み後のファイルポインタ位置: " . $file->ftell() . " バイト\n\n";
44
45    // 現在のファイルポインタ位置を記憶する(これはおおよそLine 3の開始位置になります)
46    $savedOffset = $file->ftell();
47    echo "現在のオフセットを記憶しました: " . $savedOffset . " バイト\n\n";
48
49    // さらに2行を読み込む (Line 3, Line 4)
50    echo "--- さらに2行を読み込み中 ---\n";
51    while (!$file->eof() && $lineNumber <= 4) {
52        $line = $file->fgets();
53        echo "読み込んだ行 {$lineNumber}: " . trim($line) . "\n";
54        $lineNumber++;
55    }
56    echo "4行読み込み後のファイルポインタ位置: " . $file->ftell() . " バイト\n\n";
57
58    // fseek を使って、記憶したオフセット(Line 3 の開始位置)に戻る
59    // SEEK_SET は、オフセットがファイルの先頭からの絶対バイト数であることを示します
60    echo "--- fseek を使って記憶したオフセット (" . $savedOffset . " バイト) に戻ります ---\n";
61    $returnCode = $file->fseek($savedOffset, SEEK_SET);
62
63    // fseek は成功時に 0 を、失敗時に -1 を返します
64    if ($returnCode === 0) {
65        echo "fseek 成功。現在のファイルポインタ位置: " . $file->ftell() . " バイト\n\n";
66
67        // 記憶した位置から再度2行を読み込む
68        echo "--- 記憶したオフセットから2行を再読み込み中 ---\n";
69        // 再読み込みは Line 3 から開始されます
70        $reReadLineNumber = 3; 
71        while (!$file->eof() && $reReadLineNumber <= 4) {
72            $line = $file->fgets();
73            echo "再読み込み行 {$reReadLineNumber}: " . trim($line) . "\n";
74            $reReadLineNumber++;
75        }
76        echo "再読み込み後のファイルポインタ位置: " . $file->ftell() . " バイト\n\n";
77    } else {
78        echo "fseek 失敗 (戻り値: {$returnCode})。\n";
79    }
80
81} catch (RuntimeException $e) {
82    // ファイル操作中にエラーが発生した場合
83    echo "エラーが発生しました: " . $e->getMessage() . "\n";
84} finally {
85    // スクリプト終了時に作成した一時ファイルを削除する
86    if (file_exists($filePath)) {
87        unlink($filePath);
88        echo "一時ファイル '{$filePath}' を削除しました。\n";
89    }
90}

SplFileObject::fseekメソッドは、ファイル内の読み書き位置を示すファイルポインタを、指定したバイト数だけ移動させるために使用されます。

このメソッドは2つの引数を取ります。1つ目の$offsetは、ファイルポインタを移動させるバイト数を指定します。2つ目の$whenceは、$offsetの基準となる位置を示す定数で、ファイルの先頭からの絶対位置を指定するSEEK_SET、現在の位置からの相対位置を示すSEEK_CUR、ファイルの末尾からの相対位置を示すSEEK_ENDなどがあります。メソッドの実行に成功すると0を、失敗すると-1を返します。

サンプルコードでは、ファイルを途中まで読み進めた後、fseekを使って以前の読み込み位置に戻るシナリオを示しています。fseekは行番号を直接指定するものではなく、バイト単位でファイルポインタを移動させます。しかし、ftellメソッドで現在のファイルポインタ位置(バイトオフセット)を記憶しておくことで、後からその記憶した位置にfseekを使って正確に戻ることが可能です。これにより、特定の行から処理をやり直したり、ファイルを巻き戻して情報を再読み込みしたりする際に役立ちます。例えば、ファイルの最初の数行を読み込んだ後、その時点でのファイルポインタ位置を記憶し、さらに読み進めた後で記憶した位置に戻り、再度同じ行から読み込み直すといった使い方ができます。

SplFileObject::fseekは、ファイルポインタを「バイト単位のオフセット」で移動させるメソッドです。そのため、ファイル内の行番号を直接指定して移動することはできません。特定の行の開始位置に戻りたい場合は、事前にftell()メソッドでその行のバイトオフセットを記憶し、後でfseek()にそのオフセットとSEEK_SET(ファイルの先頭からの絶対位置)を渡して移動させます。fseekは、ファイルポインタの移動に成功すると0を、失敗すると-1を返しますので、戻り値を確認して処理の成否を判断することが重要です。ファイル操作が完了したら、unlink()関数などで不要な一時ファイルを確実に削除し、リソースの適切な管理を心がけてください。

関連コンテンツ

【PHP8.x】SplFileObject::fseek()メソッドの使い方 | いっしー@Webエンジニア