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

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

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

作成日: 更新日:

基本的な使い方

seekメソッドは、FilesystemIteratorオブジェクトがファイルシステム上の要素を繰り返し処理する際に、現在注目している位置(内部的なカーソル)を移動させるメソッドです。このメソッドを使用すると、イテレータが扱っているファイルやディレクトリのリストの中から、特定の順番に位置する要素に直接アクセスできるようになります。具体的には、引数として0から始まる整数値(インデックス)を指定することで、イテレータは指定されたインデックスに対応するファイルまたはディレクトリに自身の位置を移動させます。例えば、ディレクトリ内のたくさんのファイルの中から、先頭から数えて10番目のファイルに直接移動してその情報を取得したい場合などに便利です。この機能により、リストの最初から順にすべての要素をたどる必要がなくなり、特定の要素に素早くアクセスして処理を行うことが可能になります。もし指定したインデックスが有効な範囲外であったり、該当する要素が存在しなかったりする場合には、エラーが発生する可能性がありますので注意が必要です。

構文(syntax)

1<?php
2$iterator = new FilesystemIterator('/tmp');
3
4$iterator->seek(0);
5echo $iterator->getFilename();
6?>

引数(parameters)

int $offset

  • int $offset: 移動したい位置を整数で指定します

戻り値(return)

戻り値なし

戻り値はありません

サンプルコード

FilesystemIterator::seek() でファイルにシークする

1<?php
2
3/**
4 * FilesystemIterator::seek() メソッドの使用例を示します。
5 *
6 * この関数は一時ディレクトリを作成し、複数のダミーファイルを配置します。
7 * その後、FilesystemIterator を使用してディレクトリ内のファイルを反復処理し、
8 * seek() メソッドでイテレータを特定のオフセットに移動させる方法をデモンストレーションします。
9 * FilesystemIterator は PHP の SeekableIterator インターフェースを実装しており、
10 * これにより seek() メソッドが利用可能となります。
11 */
12function demonstrateFilesystemIteratorSeek(): void
13{
14    // 一時ディレクトリを作成します。
15    $tempDir = __DIR__ . '/temp_filesystem_seek_demo';
16    if (!mkdir($tempDir) && !is_dir($tempDir)) {
17        echo "エラー: 一時ディレクトリ '{$tempDir}' を作成できませんでした。\n";
18        return;
19    }
20
21    // デモンストレーション用のダミーファイルを複数作成します。
22    // ファイル名はソートされることが多いため、アルファベット順になるようにしています。
23    file_put_contents($tempDir . '/alpha.txt', 'Content for Alpha');
24    file_put_contents($tempDir . '/beta.txt', 'Content for Beta');
25    file_put_contents($tempDir . '/gamma.txt', 'Content for Gamma');
26    file_put_contents($tempDir . '/delta.txt', 'Content for Delta');
27
28    echo "--- ディレクトリ内のファイル一覧 ---\n";
29    // FilesystemIterator のインスタンスを作成します。
30    // FilesystemIterator::SKIP_DOTS フラグは '.' と '..' エントリをスキップします。
31    $iterator = new FilesystemIterator($tempDir, FilesystemIterator::SKIP_DOTS);
32
33    // イテレータをリワインドし、最初の要素から始めます。
34    $iterator->rewind();
35
36    // ディレクトリの内容を一度すべて表示し、インデックスを確認します。
37    $index = 0;
38    foreach ($iterator as $fileInfo) {
39        echo "インデックス {$index}: {$fileInfo->getFilename()}\n";
40        $index++;
41    }
42
43    echo "\n--- FilesystemIterator::seek() のデモンストレーション ---\n";
44
45    // イテレータを特定のオフセットに移動させます。
46    // 例えば、インデックス 1 (2番目のファイル) にシークします。
47    // FilesystemIterator は SeekableIterator インターフェースを実装しているため、seek() が利用可能です。
48    $targetOffset = 1; // 0始まりのインデックスで、これは2番目のファイル(例: beta.txt)を指します。
49    try {
50        $iterator->seek($targetOffset);
51        echo "オフセット {$targetOffset} (2番目のファイル) にシークします。\n";
52
53        // seek() 後にイテレータが有効な位置にあるか確認します。
54        if ($iterator->valid()) {
55            echo "現在のファイル: {$iterator->current()->getFilename()}\n";
56        } else {
57            echo "オフセット {$targetOffset} は有効ではありません(範囲外またはディレクトリが空です)。\n";
58        }
59
60        // 次のファイルに移動します (current() が指すファイルの次)。
61        $iterator->next();
62        echo "次のファイルに移動します (現在のオフセット: " . ($targetOffset + 1) . ")...\n";
63        if ($iterator->valid()) {
64            echo "現在のファイル: {$iterator->current()->getFilename()}\n";
65        } else {
66            echo "これ以上ファイルはありません。\n";
67        }
68
69        // 別のオフセットにシークし、最初のファイルに戻ります。
70        $anotherOffset = 0; // 0番目のファイル (alpha.txt)
71        $iterator->seek($anotherOffset);
72        echo "オフセット {$anotherOffset} (1番目のファイル) にシークし直します。\n";
73        if ($iterator->valid()) {
74            echo "現在のファイル: {$iterator->current()->getFilename()}\n";
75        } else {
76            echo "オフセット {$anotherOffset} は有効ではありません。\n";
77        }
78
79    } catch (OutOfBoundsException $e) {
80        // 存在しないオフセットにシークしようとすると、この例外がスローされます。
81        echo "シーク中にエラーが発生しました: " . $e->getMessage() . "\n";
82    }
83
84    // デモンストレーション後に一時ディレクトリとファイルをクリーンアップします。
85    echo "\n--- 一時ディレクトリのクリーンアップ ---\n";
86    foreach (new FilesystemIterator($tempDir, FilesystemIterator::SKIP_DOTS) as $file) {
87        unlink($file->getPathname()); // ファイルを削除
88    }
89    rmdir($tempDir); // ディレクトリを削除
90    echo "一時ディレクトリ '{$tempDir}' とその中のファイルが削除されました。\n";
91}
92
93// デモンストレーション関数を実行します。
94demonstrateFilesystemIteratorSeek();

PHP 8のFilesystemIteratorクラスに属するseekメソッドは、ディレクトリ内のファイルリストを扱うイテレータを、指定されたインデックス(位置)に直接移動させるための機能です。FilesystemIteratorSeekableIteratorインターフェースを実装しているため、このseekメソッドを利用できます。

seekメソッドはint $offsetという引数を受け取ります。これは、ファイルリストの0から始まるインデックスを指定し、例えば$offset1を指定すると、リストの2番目のファイルにイテレータが移動します。このメソッド自体は戻り値を持ちませんが、指定されたオフセットがファイルリストの範囲外であった場合、OutOfBoundsExceptionがスローされる可能性があります。

提供されたサンプルコードでは、一時ディレクトリに複数のダミーファイルを作成し、FilesystemIteratorでそれらのファイルを準備します。その後、seek(1)を実行して2番目のファイルにイテレータを移動させ、そのファイル名を表示する様子が示されています。さらにseek(0)で最初のファイルに戻る操作も確認できます。このseekメソッドを使うことで、ディレクトリ内のすべてのファイルを順に処理することなく、必要なファイルに直接アクセスでき、特に大量のファイルの中から特定のファイルに効率的にアクセスしたい場合に有用です。

FilesystemIterator::seek()メソッドは、SeekableIteratorインターフェースを実装しているため利用できます。引数の$offsetは0から始まるインデックスで、イテレータをその位置に直接移動させます。存在しないオフセットを指定するとOutOfBoundsExceptionが発生するため、必ずtry-catchで例外処理を行ってください。シーク後には、イテレータが有効な位置にあるかをvalid()メソッドで確認することが重要です。このメソッド自体は戻り値を返しませんので、操作の成功はイテレータの状態変化で判断します。シーク後のcurrent()next()は、移動した新しい位置から動作することに留意してください。

PHP FilesystemIterator::seek でファイル位置を移動する

1<?php
2
3// Create a temporary directory for demonstration purposes
4$tempDir = sys_get_temp_dir() . DIRECTORY_SEPARATOR . 'filesystem_iterator_seek_demo_' . uniqid();
5if (!mkdir($tempDir) && !is_dir($tempDir)) {
6    die("Failed to create temporary directory: " . $tempDir);
7}
8
9// Create some dummy files in the temporary directory
10$fileNames = ['apple.txt', 'banana.txt', 'cherry.txt', 'date.txt'];
11foreach ($fileNames as $fileName) {
12    file_put_contents($tempDir . DIRECTORY_SEPARATOR . $fileName, "Content of " . $fileName);
13}
14
15echo "Created files in: " . $tempDir . "\n\n";
16
17try {
18    // Initialize FilesystemIterator for the temporary directory.
19    // FilesystemIterator::SKIP_DOTS: Skips '.' and '..' entries.
20    // FilesystemIterator::CURRENT_AS_FILEINFO: Makes current() return SplFileInfo objects.
21    $iterator = new FilesystemIterator($tempDir, FilesystemIterator::SKIP_DOTS | FilesystemIterator::CURRENT_AS_FILEINFO);
22
23    echo "--- Initial Iteration Order ---\n";
24    // First, iterate and store the file names to understand the order
25    // This simulates how one might conceptualize the files as an array-like list.
26    $initialFiles = [];
27    foreach ($iterator as $key => $fileInfo) {
28        $initialFiles[] = $fileInfo->getFilename();
29        echo "  Index: " . (count($initialFiles) - 1) . ", File: " . $fileInfo->getFilename() . "\n";
30    }
31    echo "\n";
32
33    echo "--- Demonstrating FilesystemIterator::seek() ---\n";
34
35    // Use seek() to jump directly to the first file (offset 0)
36    $targetOffset = 0;
37    if (isset($initialFiles[$targetOffset])) {
38        // FilesystemIterator::seek() moves the iterator's internal pointer
39        // to the specified offset within the sequence of items it iterates over.
40        // It's similar to accessing an element by index in an array.
41        $iterator->seek($targetOffset);
42        echo "Seeking to offset {$targetOffset} (first item). Current file: " . $iterator->current()->getFilename() . "\n";
43        // Verify it matches the expected file based on initial iteration order
44        if ($iterator->current()->getFilename() === $initialFiles[$targetOffset]) {
45            echo "  (Matches expected: {$initialFiles[$targetOffset]})\n";
46        }
47    }
48
49    // Use seek() to jump directly to the third file (offset 2)
50    $targetOffset = 2;
51    if (isset($initialFiles[$targetOffset])) {
52        $iterator->seek($targetOffset);
53        echo "Seeking to offset {$targetOffset} (third item). Current file: " . $iterator->current()->getFilename() . "\n";
54        if ($iterator->current()->getFilename() === $initialFiles[$targetOffset]) {
55            echo "  (Matches expected: {$initialFiles[$targetOffset]})\n";
56        }
57    }
58
59    // Attempt to seek to an offset that is out of bounds
60    $targetOffset = count($initialFiles) + 5; // An offset clearly beyond the last item
61    echo "\nAttempting to seek to offset {$targetOffset} (out of bounds)...\n";
62    $iterator->seek($targetOffset);
63    // After seeking past the end, the iterator becomes invalid.
64    // The valid() method checks if the iterator is at a valid position.
65    if ($iterator->valid()) {
66        echo "  Iterator is still valid, pointing to: " . $iterator->current()->getFilename() . " (Unexpected for out of bounds)\n";
67    } else {
68        echo "  Iterator is no longer valid after seeking to an out-of-bounds offset, which is expected.\n";
69    }
70    echo "\n";
71
72    // Demonstrate seeking back to a valid position (e.g., the beginning)
73    // after the iterator has become invalid or was at the end.
74    $targetOffset = 0;
75    if (isset($initialFiles[$targetOffset])) {
76        $iterator->seek($targetOffset);
77        echo "Seeking back to offset {$targetOffset} (first item). Current file: " . $iterator->current()->getFilename() . "\n";
78        if ($iterator->current()->getFilename() === $initialFiles[$targetOffset]) {
79            echo "  (Matches expected: {$initialFiles[$targetOffset]})\n";
80        }
81    }
82
83} catch (Exception $e) {
84    echo "An error occurred: " . $e->getMessage() . "\n";
85} finally {
86    // Cleanup: Remove dummy files and the temporary directory
87    foreach ($fileNames as $fileName) {
88        $filePath = $tempDir . DIRECTORY_SEPARATOR . $fileName;
89        if (file_exists($filePath)) {
90            unlink($filePath);
91        }
92    }
93    if (is_dir($tempDir)) {
94        rmdir($tempDir);
95    }
96    echo "\nCleaned up temporary directory: " . $tempDir . "\n";
97}

PHPのFilesystemIterator::seekメソッドは、ディレクトリ内のファイルやサブディレクトリを順に処理するFilesystemIteratorの内部ポインタを、指定した位置へ直接移動させるために使用します。

このメソッドの引数$offsetには、イテレータが扱う項目(ファイルやディレクトリ)のリストにおける、0から始まるインデックス(位置)を整数で指定します。例えば、seek(0)はリストの最初の項目へ、seek(2)は3番目の項目へイテレータを移動させます。

seekを実行すると、イテレータの内部ポインタが指定されたオフセットに設定され、その後current()メソッドを呼び出すことで、その位置にある項目(このサンプルコードではファイル情報)を取得できるようになります。これは、配列のインデックスを使って特定の要素に直接アクセスする操作に似ています。

もし存在しない、つまりリストの範囲外のオフセットを指定した場合、イテレータは無効な状態となり、valid()メソッドはfalseを返します。しかし、一度無効になった後でも、再度有効なオフセットにseekすることで、イテレータを再利用し、処理を続けることが可能です。このメソッド自体は、特別な戻り値を持ちません(void)。

FilesystemIterator::seek()は、ディレクトリ内のファイルやフォルダを順に処理するイテレータの内部ポインタを、指定した数値のオフセットに直接移動させる機能です。オフセットは0から始まる整数のインデックスのように扱われます。存在しない範囲のオフセットを指定すると、イテレータは無効な状態となり、その後のcurrent()などの呼び出しでエラーとなる可能性があります。そのため、seek()後にvalid()メソッドでイテレータの状態を確認することが重要です。無効になった場合でも、有効なオフセットで再度seek()を呼び出すことで、イテレータを有効な状態に戻すことができます。ファイルの並び順はファイルシステムの物理的な順序に依存しますので、注意が必要です。

関連コンテンツ