サーチ…
構文
- int readfile(文字列$ filename [、bool $ use_include_path = false [、リソース$コンテキスト]])
パラメーター
パラメータ | 説明 |
---|---|
ファイル名 | 読み込まれるファイル名。 |
use_include_path | include_pathでファイルを検索する場合は、オプションの2番目のパラメータを使用してTRUEに設定することもできます。 |
コンテキスト | コンテキストストリームリソース。 |
備考
ファイル名の構文
このトピックの関数に渡されるほとんどのファイル名は次のとおりです。
- 自然界の弦。
- ファイル名は直接渡すことができます。他の型の値が渡された場合、それらはstringにキャストされます。これは、
DirectoryIterator
の反復における値であるSplFileInfo
に特に便利です。
- ファイル名は直接渡すことができます。他の型の値が渡された場合、それらはstringにキャストされます。これは、
- 相対的または絶対的。
- プロトコルを受け入れる。
- 彼らは
scheme://
管理し、プロトコルラッパーを管理するように指定することができます。たとえば、file_get_contents("http://example.com")
はhttp://example.comからコンテンツを取得します。
- 彼らは
- スラッシュ対応。
- Windowsの
DIRECTORY_SEPARATOR
はバックスラッシュで、システムはデフォルトでパスのバックスラッシュを返しますが、開発者は/
をディレクトリ区切り文字として引き続き使用できます。したがって、互換性のために、開発者は/
をすべてのシステム上のディレクトリ区切り文字として使用できますが、関数によって返される値(たとえばrealpath
)にはバックスラッシュが含まれる可能性があることに注意してください。
- Windowsの
ファイルとディレクトリの削除
ファイルの削除
unlink
関数は、単一のファイルを削除し、操作が成功したかどうかを返します。
$filename = '/path/to/file.txt';
if (file_exists($filename)) {
$success = unlink($filename);
if (!$success) {
throw new Exception("Cannot delete $filename");
}
}
再帰的削除によるディレクトリの削除
一方、ディレクトリはrmdir
で削除する必要がありrmdir
。ただし、この関数は空のディレクトリのみを削除します。ファイルを含むディレクトリを削除するには、まずディレクトリ内のファイルを削除します。ディレクトリにサブディレクトリが含まれている場合は、 再帰が必要な場合があります。
次の例では、ディレクトリ内のファイルをスキャンし、メンバーファイル/ディレクトリを再帰的に削除し、削除されたファイル(ディレクトリではない)の数を返します。
function recurse_delete_dir(string $dir) : int {
$count = 0;
// ensure that $dir ends with a slash so that we can concatenate it with the filenames directly
$dir = rtrim($dir, "/\\") . "/";
// use dir() to list files
$list = dir($dir);
// store the next file name to $file. if $file is false, that's all -- end the loop.
while(($file = $list->read()) !== false) {
if($file === "." || $file === "..") continue;
if(is_file($dir . $file)) {
unlink($dir . $file);
$count++;
} elseif(is_dir($dir . $file)) {
$count += recurse_delete_dir($dir . $file);
}
}
// finally, safe to delete directory!
rmdir($dir);
return $count;
}
便利な機能
Raw direct IO
file_get_contents
とfile_put_contents
は、1回の呼び出しでPHP文字列との間でファイルを読み書きする機能を提供します。
file_put_contents
をFILE_APPEND
ビットマスクフラグと共に使用して、ファイルを切り捨ておよび上書きするのではなく、追加することもできます。これは、 LOCK_EX
ビットマスクと共に使用して、書き込みに進む間にファイルへの排他ロックを取得します。ビットマスクフラグは、 |
ビット単位OR演算子。
$path = "file.txt";
// reads contents in file.txt to $contents
$contents = file_get_contents($path);
// let's change something... for example, convert the CRLF to LF!
$contents = str_replace("\r\n", "\n", $contents);
// now write it back to file.txt, replacing the original contents
file_put_contents($path, $contents);
FILE_APPEND
はログファイルへの追加に便利ですが、 LOCK_EX
は複数のプロセスからのファイル書き込みの競合状態の防止に役立ちます。たとえば、現在のセッションについてログファイルに書き込むには、次のようにします。
file_put_contents("logins.log", "{$_SESSION["username"]} logged in", FILE_APPEND | LOCK_EX);
CSV IO
fgetcsv($file, $length, $separator)
fgetcsv
は、csvフィールドのオープンファイルチェックから行を解析します。成功FALSE
配列のCSVフィールドを返し、失敗したFALSE
を返します。
デフォルトでは、CSVファイルの1行だけが読み込まれます。
$file = fopen("contacts.csv","r");
print_r(fgetcsv($file));
print_r(fgetcsv($file,5," "));
fclose($file);
contacts.csv
Kai Jim, Refsnes, Stavanger, Norway
Hege, Refsnes, Stavanger, Norway
出力:
Array
(
[0] => Kai Jim
[1] => Refsnes
[2] => Stavanger
[3] => Norway
)
Array
(
[0] => Hege,
)
直接stdoutにファイルを読み込む
readfile
はファイルを出力バッファにコピーします。 readfile()は大きなファイルを送信してもメモリの問題を表示しません。
$file = 'monkey.gif';
if (file_exists($file)) {
header('Content-Description: File Transfer');
header('Content-Type: application/octet-stream');
header('Content-Disposition: attachment; filename="'.basename($file).'"');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize($file));
readfile($file);
exit;
}
またはファイルポインタから
代わりに、stdoutにコピーを開始するファイル内のポイントを探すには、代わりにfpassthru
使用します。次の例では、最後の1024バイトがstdoutにコピーされます。
$fh = fopen("file.txt", "rb");
fseek($fh, -1024, SEEK_END);
fpassthru($fh);
ファイルを配列に読み込む
file
は渡されたファイルの行を配列に返します。配列の各要素は、ファイル内の行に対応し、改行はまだ添付されています。
print_r(file("test.txt"));
test.txt
Welcome to File handling
This is to test file handling
出力:
Array
(
[0] => Welcome to File handling
[1] => This is to test file handling
)
ファイル情報の取得
パスがディレクトリかファイルかを確認する
is_dir
関数は、引数がディレクトリかどうかを返しますis_file
は、引数がファイルかどうかを返します。それがどちらかであるかどうかを確認するには、 file_exists
を使用します。
$dir = "/this/is/a/directory";
$file = "/this/is/a/file.txt";
echo is_dir($dir) ? "$dir is a directory" : "$dir is not a directory", PHP_EOL,
is_file($dir) ? "$dir is a file" : "$dir is not a file", PHP_EOL,
file_exists($dir) ? "$dir exists" : "$dir doesn't exist", PHP_EOL,
is_dir($file) ? "$file is a directory" : "$file is not a directory", PHP_EOL,
is_file($file) ? "$file is a file" : "$file is not a file", PHP_EOL,
file_exists($file) ? "$file exists" : "$file doesn't exist", PHP_EOL;
これは与える:
/this/is/a/directory is a directory
/this/is/a/directory is not a file
/this/is/a/directory exists
/this/is/a/file.txt is not a directory
/this/is/a/file.txt is a file
/this/is/a/file.txt exists
ファイルタイプの確認
filetype
を使用して、 filetype
をチェックします。次のようになります。
-
fifo
-
char
-
dir
-
block
-
link
-
file
-
socket
-
unknown
ファイル名をそのままfiletype
渡す:
echo filetype("~"); // dir
filetype
はfalseを返し、ファイルが存在しない場合はE_WARNING
をトリガーします。
読みやすさと書き込み可能性の確認
is_writable
関数とis_readable
関数にファイル名をis_writable
と、ファイルが書き込み可能か読み取り可能かをそれぞれチェックします。
ファイルが存在しない場合、関数は正常にfalse
返しfalse
。
ファイルアクセスの確認/修正
filemtime
およびfileatime
を使用すると、ファイルの最後の変更またはアクセスのタイムスタンプが返されます。戻り値はUNIXのタイムスタンプです。詳細は日付と時刻の処理を参照してください。
echo "File was last modified on " . date("Y-m-d", filemtime("file.txt"));
echo "File was last accessed on " . date("Y-m-d", fileatime("file.txt"));
fileinfoでパス部分を取得する
$fileToAnalyze = ('/var/www/image.png');
$filePathParts = pathinfo($fileToAnalyze);
echo '<pre>';
print_r($filePathParts);
echo '</pre>';
この例は次のように出力されます:
Array
(
[dirname] => /var/www
[basename] => image.png
[extension] => png
[filename] => image
)
次のように使用できます。
$filePathParts['dirname']
$filePathParts['basename']
$filePathParts['extension']
$filePathParts['filename']
パラメータ | 詳細 |
---|---|
$パス | パースされるファイルのフルパス |
$オプション | 利用可能な4つのオプションのうちの1つ[PATHINFO_DIRNAME、PATHINFO_BASENAME、PATHINFO_EXTENSION、PATHINFO_FILENAME] |
- オプション(第2引数)が渡されない場合、連想配列が返されます。そうでない場合は、文字列が返されます。
- ファイルが存在することを検証しません。
- 文字列を部分的に解析します。ファイルの検証は行われません(MIMEタイプのチェックなどはありません)
- 拡張子は単に
$path
の最後の拡張子ですimage.jpg.png
ファイルのパスは、技術的には.jpg
ファイルでも.png
なります。拡張子のないファイルは、配列の拡張要素を返しません。
大容量ファイルを処理する際のメモリ使用量を最小限に抑える
大規模なファイル、たとえば何百万もの行を含む10Mバイト以上のCSVファイルを解析する必要がある場合、 file
またはfile_get_contents
関数を使用して、 memory_limit
設定で
XXXXXバイトのメモリサイズを使い果たしました
エラー。次のソースを考えてみましょう(top-1m.csvは100万行あり、約22Mバイトです)
var_dump(memory_get_usage(true));
$arr = file('top-1m.csv');
var_dump(memory_get_usage(true));
これは、
int(262144)
int(210501632)
インタプリタはすべての行を$arr
配列に保持する必要があったため、RAMの消費量は約200Mバイトでした。配列の内容については何もしていないことに注意してください。
次のコードを考えてみましょう:
var_dump(memory_get_usage(true));
$index = 1;
if (($handle = fopen("top-1m.csv", "r")) !== FALSE) {
while (($row = fgetcsv($handle, 1000, ",")) !== FALSE) {
file_put_contents('top-1m-reversed.csv',$index . ',' . strrev($row[1]) . PHP_EOL, FILE_APPEND);
$index++;
}
fclose($handle);
}
var_dump(memory_get_usage(true));
どの出力
int(262144)
int(262144)
余分な1バイトのメモリを使用するのではなく、CSV全体を解析し、2番目の列の値を逆にする別のファイルに保存します。これは、 fgetcsv
1行だけを読み込み、すべてのループで$row
が上書きされるためです。
ストリームベースのファイルIO
ストリームを開く
fopen
はファイルストリームハンドルをオープンします。ファイルハンドルは、読み取り、書き込み、シーク、およびその他の機能のためにさまざまな機能とともに使用できます。この値はresource
タイプであり、その機能を保持する他のスレッドに渡すことはできません。
$f = fopen("errors.log", "a"); // Will try to open errors.log for writing
2番目のパラメータは、ファイルストリームのモードです。
モード | 説明 |
---|---|
r | 読み込み専用モードで開き、ファイルの先頭から開始する |
r+ | ファイルの先頭から読み書き用に開く |
w | ファイルの先頭から書き込み専用に開きます。ファイルが存在する場合、ファイルは空になります。存在しない場合は作成しようとします。 |
w+ | ファイルの先頭から読み書き用にオープンします。ファイルが存在する場合、ファイルは空になります。存在しない場合は作成しようとします。 |
a | ファイルの最後から書き込み専用にファイルを開きます。ファイルが存在しない場合、ファイルを作成しようとします |
a+ | ファイルの最後から読み書き用のファイルを開きます。ファイルが存在しない場合、ファイルを作成しようとします |
x | 書き込み専用のファイルを作成して開きます。ファイルが存在する場合、 fopen 呼び出しは失敗します |
x+ | 読み書き用のファイルを作成して開きます。ファイルが存在する場合、 fopen 呼び出しは失敗します |
c | 書き込み専用にファイルを開きます。ファイルが存在しない場合は、作成しようとします。ファイルの先頭に書き出しを開始しますが、書き込む前にファイルを空にしません |
c+ | 読み取りと書き込みのためにファイルを開きます。ファイルが存在しない場合は、作成しようとします。ファイルの先頭に書き出しを開始しますが、書き込む前にファイルを空にしません |
Windowsでモードの後ろにt
追加すると(例えばa+b
、 wt
など)、ファイルの操作時に"\n"
行末が"\r\n"
に変換されます。これが意図されていない場合、特にバイナリファイルの場合は、モードの後ろにb
追加してください。
PHPアプリケーションは、 Too many open files
エラーを防ぐために使用されなくなったときに、 fclose
を使用してストリームをクローズする必要があります。これは、(リソースリークを防止するための練習として、それでも必要があります )Webサーバに、それは必要ないかもしれないということを意味ストリームを閉じます-ランタイムのシャットダウン時にストリームのみ閉じているので、これは、CLIプログラムでは特に重要ですプロセスが長時間実行されることを期待していない場合、多くのストリームを開くことはありません。
読書
fread
を使うと、指定されたバイト数がファイルポインタから読み込まれるか、またはEOFが満たされるまで読み込まれます。
行を読む
fgets
を使用すると、EOLに達するか、指定された長さが読み取られるまでファイルが読み込まれます。
fread
とfgets
両方は、読み込み中にファイルポインタを移動します。
残りのすべてを読む
stream_get_contents
を使用すると、ストリーム内の残りのすべてのバイトが文字列に変換され、返されます。
ファイルポインタの位置を調整する
最初にストリームを開いた後、ファイルポインタはファイルの先頭にあります(または、モードa
が使用されている場合は最後です)。 fseek
関数を使用すると、ファイルポインタが次の3つの値のいずれかを基準にして新しい位置に移動します。
-
SEEK_SET
:これがデフォルト値です。ファイル位置のオフセットはファイルの先頭からの相対的な値になります。 -
SEEK_CUR
:ファイル位置のオフセットは、現在の位置からの相対的なオフセットになります。 -
SEEK_END
:ファイルの位置のオフセットは、ファイルの終わりを基準にして相対的になります。この値には、負のオフセットを渡すことが最も一般的です。ファイルの終わりの前に指定されたバイト数にファイルの位置を移動します。
rewind
はfseek($fh, 0, SEEK_SET)
便利なショートカットです。
ftell
を使用すると、ファイルポインタの絶対位置が表示されます。
たとえば、次のスクリプトは最初の10バイトをスキップし、次の10バイトを読み込み、10バイトをスキップし、次の10バイトを読み込み、次にfile.txtの最後の10バイトを読み込みます。
$fh = fopen("file.txt", "rb");
fseek($fh, 10); // start at offset 10
echo fread($fh, 10); // reads 10 bytes
fseek($fh, 10, SEEK_CUR); // skip 10 bytes
echo fread($fh, 10); // read 10 bytes
fseek($fh, -10, SEEK_END); // skip to 10 bytes before EOF
echo fread($fh, 10); // read 10 bytes
fclose($fh);
書き込み
fwrite
を使用すると、指定された文字列が現在のファイルポインタから始まるファイルに書き込まれます。
fwrite($fh, "Some text here\n");
ファイルとディレクトリの移動とコピー
ファイルのコピー
copy
は、第1引数のソースファイルを第2引数のcopy
コピーします。解決された宛先は、すでに作成されたディレクトリ内にある必要があります。
if (copy('test.txt', 'dest.txt')) {
echo 'File has been copied successfully';
} else {
echo 'Failed to copy file to destination given.'
}
再帰を伴うディレクトリのコピー
ディレクトリのコピーはディレクトリの削除とほぼ同じですが、 unlink
ではなくファイルのcopy
が使用されunlink
が、ディレクトリではrmdir
ではなくmkdir
が使用されます。
function recurse_delete_dir(string $src, string $dest) : int {
$count = 0;
// ensure that $src and $dest end with a slash so that we can concatenate it with the filenames directly
$src = rtrim($dest, "/\\") . "/";
$dest = rtrim($dest, "/\\") . "/";
// use dir() to list files
$list = dir($src);
// create $dest if it does not already exist
@mkdir($dest);
// store the next file name to $file. if $file is false, that's all -- end the loop.
while(($file = $list->read()) !== false) {
if($file === "." || $file === "..") continue;
if(is_file($src . $file)) {
copy($src . $file, $dest . $file);
$count++;
} elseif(is_dir($src . $file)) {
$count += recurse_copy_dir($src . $file, $dest . $file);
}
}
return $count;
}
名前の変更/移動
ファイルやディレクトリの名前を変更/移動する方がはるかに簡単です。 rename
機能を使用して、単一の呼び出しでディレクトリ全体を移動またはrename
ます。
rename("~/file.txt", "~/file.html");
rename("~/dir", "~/old_dir");
rename("~/dir/file.txt", "~/dir2/file.txt");