在本文中,我们介绍了PHP中的文件系统函数。我们使用文件和目录,确定文件权限和可用磁盘空间,以及读取和写入文件。对于我们的示例,我们使用PHPCLI。PHP教程是ZetCode上PHP语言的简明教程。
$ php -v php -v PHP 8.1.2 (cli) (built: Aug 8 2022 07:28:23) (NTS) ...
我们使用PHP版本8.1.2。
PHP有一组丰富的函数来处理文件和目录。PHP包含低级和高级文件系统函数。fopen函数是低级函数的一个例子;它是类似C函数的薄包装。file函数是高级PHP文件系统函数的示例。
PHP文件大小和类型
filesize函数返回给定文件的大小。大小以字节为单位指定。
<?php $filename = "fruits.txt"; $fsize = filesize($filename); echo "The file size is: $fsize bytes\n";
在示例中,我们确定了fruits.txt文件的大小。该文件位于当前工作目录中,即与PHP脚本位于同一目录中。
$ php get_filesize.php The file size is: 40 bytes
fruits.txt文件的大小为40字节。
filetype函数获取一个文件的类型,可能的返回值有:fifo、char、dir、block、link、file、socket和unknown。p>
<?php
echo filetype("myfile") . PHP_EOL;
echo filetype(".") . PHP_EOL;
echo filetype("/dev/tty1") . PHP_EOL;
echo filetype("/var/run/cups/cups.sock") . PHP_EOL;
脚本决定了四个文件的类型。
$ php file_types.php file dir char socket
这四个文件分别是常规文件、目录、字符设备和套接字。
PHP检查文件是否存在
我们可能会想使用一个不存在的文件。file_exists函数可用于防止这种情况。
<?php
if ($argc != 2) {
exit("Usage: file_existence.php filename\n");
}
$filename = $argv[1];
$r = file_exists($filename);
if (!$r) {
exit("Cannot determine the size of the file; the file does not exist\n");
}
$fsize = filesize($filename);
echo "The file size is: $fsize bytes\n";
此脚本在计算文件大小之前检查给定文件是否存在。
if ($argc != 2) {
exit("Usage: file_existence.php filename\n");
}
$argc是一个特殊变量,它包含传递给脚本的参数数量。我们需要两个参数:一个脚本名称和另一个作为参数传递的文件名。
$filename = $argv[1];
$argv是传递给脚本的参数数组。我们得到第二个元素。
$r = file_exists($filename);
if (!$r) {
exit("Cannot determine the size of the file; the file does not exist\n");
}
我们使用file_exists函数检查文件是否存在。如果不存在,我们将终止脚本并显示一条消息。
$ php file_existence.php fruits.txt The file size is: 40 bytes
这是file_existence.php脚本的示例输出。
在下面的示例中,我们创建一个新文件,将其删除,并检查其是否存在。touch函数设置文件的访问和修改时间。如果文件不存在,则创建它。unlink函数删除一个文件。
<?php
$filename = "newfile.txt";
if (file_exists($filename)) {
echo "The file $filename exists\n";
} else {
echo "The file $filename does not exist\n";
$r = touch($filename);
if (!$r) {
exit("Failed to touch $filename file\n");
} else {
echo "The file $filename has been created\n";
}
}
$r = unlink($filename);
if ($r) {
echo "The file $filename was deleted\n";
} else {
exit("Failed to delete $filename file\n");
}
if (file_exists($filename)) {
echo "The file $filename exists\n";
} else {
echo "The file $filename does not exist\n";
}
在代码示例中,我们使用了所有三个函数:file_exists、touch和unlink。
$r = touch($filename);
touch函数用于创建一个名为newfile.txt的新文件。
if (!$r) {
exit("Failed to touch $filename file\n");
} else {
echo "The file $filename has been created\n";
}
如果touch功能失败,将打印一条错误消息。许多PHP函数在失败时返回一个false值。
$r = unlink($filename);
unlink函数删除文件。
$ php file_existence2.php The file newfile.txt does not exist The file newfile.txt has been created The file newfile.txt was deleted The file newfile.txt does not exist
这是file_existence2.php的输出。
PHP复制和重命名文件
copy函数复制一个文件,rename函数重命名一个文件。如果目标文件已经存在,它将被覆盖。
<?php
$r = copy("myfile.txt", "myfile2.txt");
if ($r) {
echo "Successfully copied file\n";
} else {
exit("Failed to copy file\n");
}
脚本复制一个文件。
<?php
$r = rename("myfile2.txt", "myfile_back.txt");
if ($r) {
echo "Successfully renamed file\n";
} else {
exit("Failed to rename file\n");
}
在此脚本中,我们使用rename函数将myfile2.txt文件重命名为myfile_back.txt。
E_WARNING
某些文件系统函数在失败时发出E_WARNING。这是一个运行时警告(非致命错误)。脚本的执行不会停止。
PHP在这方面并不一致;并非所有文件系统函数都会发出此警告——大多数函数仅在失败时返回错误值。
<?php
set_error_handler("mywarning_handler", E_WARNING);
$r = unlink('image1.png');
if ($r) {
echo "File successfully deleted\n";
}
function mywarning_handler($errno, $errstr) {
echo "Failed to delete file\n";
echo "$errstr: $errno\n";
}
在脚本中,我们删除了一个文件并提供了一个自定义错误处理程序。
set_error_handler("mywarning_handler", E_WARNING);
使用set_error_handler函数设置自定义错误处理程序。
function mywarning_handler($errno, $errstr) {
echo "Failed to delete file\n";
echo "$errstr: $errno\n";
}
处理程序接收错误编号和错误字符串作为参数。
$ php custom_error_handler.php Failed to delete file unlink(image1.png): No such file or directory: 2
custom_error_handler.php在没有要删除的image1.png时给出此输出。
PHP目录
dirname函数返回父目录的路径。从PHP7开始,我们可以提供一个可选的levels参数,它告诉要上升的父目录的数量。
<?php
$home_dir = getenv("HOME");
echo dirname($home_dir). PHP_EOL;
echo dirname("/etc/") . PHP_EOL;
echo dirname(".") . PHP_EOL;
echo dirname("/usr/local/lib", 2) . PHP_EOL;
在脚本中,我们打印了四个目录的父目录。
$home_dir = getenv("HOME");
我们使用getenv函数获取当前用户的主目录。
echo dirname($home_dir). PHP_EOL;
此行打印用户主目录的父目录。
echo dirname(".") . PHP_EOL;
在这里,我们打印当前工作目录的父目录。
echo dirname("/usr/local/lib", 2) . PHP_EOL;
在这一行中,我们打印了/usr/local/lib目录的第二个父目录。
$ php parent_directories.php /home / . /usr
这是parent_directories.php的输出。
getcwd函数返回当前工作目录,chdir函数将当前工作目录更改为新目录。
<?php
$cd = getcwd();
echo "Current directory:" . $cd . PHP_EOL;
chdir("..");
$cd2 = getcwd();
echo "Current directory:" . $cd2 . PHP_EOL;
该脚本与getcmd和chdir函数一起使用。
$ php current_directory.php Current directory:/home/janbodnar/prog/phpfiles Current directory:/home/janbodnar/prog
这是脚本的示例输出。
PHP列表目录
在下面的五个例子中,我们列出了目录的内容。有几种方法可以完成这项任务。
<?php
$folder = '/home/janbodnar/prog';
$fh = opendir($folder);
if ($fh === false) {
exit("Cannot open directory\n");
}
while (false !== ($entry = readdir($fh))) {
echo "$entry\n";
}
closedir($fh);
opendir函数打开一个目录句柄。readdir函数从目录句柄中读取一个条目。目录句柄在脚本末尾用closedir函数关闭。
is_dir函数判断文件名是否为目录,is_file函数判断文件名是否为文件。
<?php
$folder = '/home/janbodnar/prog/';
$fh = opendir($folder);
if ($fh === false) {
exit("Cannot open directory\n");
}
$dirs = [];
$files = [];
while (false !== ($entry = readdir($fh))) {
if (is_dir($folder . '/' . $entry)) {
array_push($dirs, $entry);
}
if (is_file($folder . '/' . $entry)) {
array_push($files, $entry);
}
}
echo "Directories:\n";
foreach ($dirs as $dr) {
echo "$dr\n";
}
echo "Files:\n";
foreach ($files as $myfile) {
echo "$myfile\n";
}
closedir($fh);
在第二个示例中,我们将条目分为子目录和文件。脚本首先打印子目录,然后打印检查目录的文件。
if (is_dir($folder . '/' . $entry)) {
array_push($dirs, $entry);
}
必须将目录的完整路径提供给is_dir函数。
glob函数查找与模式匹配的路径名。
<?php
foreach (glob('/home/janbodnar/*', GLOB_ONLYDIR) as $dir) {
echo "$dir\n";
}
使用GLOB_ONLYDIR标志,glob函数仅返回与模式匹配的目录条目。
scandir是一个高级函数,用于列出指定路径中的文件和目录。该函数返回目录中的文件和目录数组。
<?php
$files = scandir('.', SCANDIR_SORT_DESCENDING);
print_r($files);
该脚本打印当前工作目录的文件和子目录数组。SCANDIR_SORT_DESCENDING标志按字母降序对条目进行排序。
在前面的例子中,我们只列出了一个目录的内容;我们没有包括子目录的元素。使用RecursiveDirectoryIterator和RecursiveIteratorIterator类我们可以使用递归轻松迭代文件系统目录。换句话说,我们遍历所有子目录,直到列出目录树中的所有项目。
<?php
$folder = '/home/janbodnar/prog/';
$rdi = new RecursiveDirectoryIterator($folder);
$rii = new RecursiveIteratorIterator($rdi);
foreach ($rii as $filename) {
echo "$filename\n";
}
该脚本打印给定目录的所有深度级别的所有项目。
PHP路径
路径是计算机文件的完整指定名称,包括文件在文件系统目录结构中的位置。realpath函数返回规范的绝对路径名,basename函数返回路径的尾随名称部分。
<?php
echo realpath("myfile.txt") . PHP_EOL;
echo basename("/home/janbodnar/prog/phpfiles/myfile.txt") . PHP_EOL;
echo basename("/home/janbodnar/prog/phpfiles/myfile.txt", ".txt") . PHP_EOL;
此脚本使用realpath和basename函数。
echo basename("/home/janbodnar/prog/phpfiles/myfile.txt", ".txt") . PHP_EOL;
如果我们指定第二个参数,后缀名,它也会从路径名中移除。
$ php paths.php /home/janbodnar/prog/phpfiles/myfile.txt myfile.txt myfile
这是paths.php示例的输出。
pathinfo函数返回有关文件路径的信息。
<?php
$path_parts = pathinfo('myfile.txt');
echo $path_parts['dirname'] . PHP_EOL;
echo $path_parts['basename'] . PHP_EOL;
echo $path_parts['extension'] . PHP_EOL;
echo $path_parts['filename'] . PHP_EOL;
该函数返回一个包含以下元素的关联数组:目录名、基名、扩展名(如果有)和文件名。
$ php path_info.php . myfile.txt txt myfile
这是输出。
PHP创建文件
fopen函数打开文件或URL。函数的第一个参数是文件名,第二个参数是我们打开窗口的模式。例如,'r'模式打开只读,'w'只写。如果我们以'w'模式打开一个文件并且它不存在,则会创建它。模式列表可以在fopen()的PHP手册中找到。
fopen返回文件句柄。这是一个用于操作文件的对象;例如,我们将它传递给fwrite函数以写入文件。
<?php
$filename = "names.txt";
if (file_exists($filename)) {
exit("The file already exists\n");
}
$fh = fopen($filename, 'w');
if ($fh === false) {
exit("Cannot create file\n");
}
echo "Successfully created file\n";
fclose($fh);
该示例创建了一个名为names.txt的新文件。
if (file_exists($filename)) {
exit("The file already exists\n");
}
首先,我们检查文件是否存在。
$fh = fopen('names.txt', 'w');
创建了names.txt文件并返回了该文件的句柄。
fclose($fh);
我们使用fclose函数关闭文件句柄。
PHP读取文件
在接下来的例子中,我们将读取文件内容。
fread从handle引用的文件指针中读取最多length个字节。一旦读取了length字节或到达EOF(文件末尾),读取就会停止。
<?php
$fh = fopen('balzac.txt', 'r');
if ($fh === false) {
exit("Cannot open file for reading\n");
}
while (!feof($fh)) {
$chunk = fread($fh, 1024);
if ($chunk === false) {
exit("Cannot read from file\n");
}
echo $chunk;
}
fclose($fh);
该示例使用fread函数读取整个文件并将其输出到控制台。
while (!feof($fh)) {
$chunk = fread($fh, 1024);
if ($chunk === false) {
exit("Cannot read from file\n");
}
echo $chunk;
}
feof测试文件指针上的文件结尾。fread每1KB块读取文件,直到到达EOF。
$ php read_file.php balzac.txt Honoré de Balzac, (born Honoré Balzac, 20 May 1799 â 18 August 1850) was a French novelist and playwright. His magnum opus was a sequence of short stories and novels collectively entitled La Comédie Humaine, which presents a panorama of French life in the years after the 1815 Fall of Napoleon Bonaparte.
这是read_file.php示例的输出。
在第二个例子中,我们使用了fgets函数,它从文件句柄中读取一行。
<?php
$fh = fopen('balzac.txt', 'r');
if ($fh === false) {
exit("Cannot open file for reading\n");
}
while (!feof($fh)) {
$line = fgets($fh);
if ($line === false) {
exit("Cannot read from file\n");
}
echo $line;
}
fclose($fh);
该示例逐行读取balzac.txt文件的内容。
file是一个高级函数,它将整个文件读取到一个数组中。
<?php
$lines = file('balzac.txt');
if ($lines === false) {
exit("Cannot read file\n");
}
foreach ($lines as $line) {
echo $line;
}
在这个例子中,我们使用file函数一次读取整个文件。我们使用foreach循环遍历返回的数组。
file_get_contents是另一个高级函数,它将整个文件读入一个字符串。
<?php
$content = file_get_contents('balzac.txt');
if ($content === false) {
exit("Cannot read file\n");
}
echo "$content";
该示例使用file_get_contents函数一次读取整个文件。它以字符串形式返回数据。
PHP读取格式化数据
fscanf函数根据格式解析来自文件的输入。每次调用fscanf都会从文件中读取一行。
$ cat items.txt coins 5 pens 6 chairs 12 books 20
我们要解析items.txt文件。
<?php
$fh = fopen("items.txt", "r");
if ($fh === false) {
exit("Cannot read file\n");
}
while ($data = fscanf($fh, "%s %d")) {
list($item, $quantity) = $data;
echo "$item: $quantity\n";
}
fclose($fh);
fscanf函数采用格式说明符来读取字符串和数字。
PHP阅读网页
PHP文件系统函数也可用于读取网页。
<?php
$ph = fopen("http://webcode.me", "r");
if ($ph === false) {
exit("Failed to open stream to URL\n");
}
while (!feof($ph)) {
$buf = fread($ph, 1024);
if ($buf === false) {
exit("Cannot read page\n");
}
echo $buf;
}
fclose($ph);
我们从一个小型网站wecode.me读取了一个页面。
$ph = fopen("http://webcode.me", "r");
使用fopen函数,我们打开网页的句柄。
while (!feof($ph)) {
$buf = fread($ph, 1024);
if ($buf === false) {
exit("Cannot read page\n");
}
echo $buf;
}
我们阅读网页直到结束;feof用于测试网页的结尾。使用fread函数以1KB的块读取页面。
$ php read_page.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>My html page</title>
</head>
<body>
<p>
Today is a beautiful day. We go swimming and fishing.
</p>
<p>
Hello there. How are you?
</p>
</body>
</html>
这是read_page.php脚本的输出。
以下示例使用高级函数读取同一网页。
<?php
$page = file_get_contents('http://webcode.me');
if ($page === false) {
exit("Cannot read page\n");
}
echo $page;
file_get_contents一次读取整个网页。
fgetss函数从文件句柄中读取一行并去除HTML标记。
<?php
$ph = fopen("http://webcode.me", "r");
if ($ph === false) {
exit("Failed to open stream to URL\n");
}
while (!feof($ph)) {
$buf = fgetss($ph, 1024);
if ($buf === false) {
exit("Cannot read from page\n");
}
echo trim($buf);
}
fclose($ph);
我们读取webcode.me网页的内容并剥离HTML标签。
echo trim($buf);
trim函数删除前导和尾随空格。
$ php read_page3.php My html pageToday is a beautiful day. We go swimming and fishing.Hello there. How are you?
这是示例的输出;输出包含页面正文中的标题和文本。
PHP写入文件
fwrite函数将字符串写入由文件句柄引用的文件。
<?php
$fh = fopen('names.txt', 'w');
if ($fh === false) {
exit("Cannot open file\n");
}
$r = fwrite($fh, 'Jane' . PHP_EOL);
check_retval($r);
$r = fwrite($fh, 'Lucy' . PHP_EOL);
check_retval($r);
$r = fwrite($fh, 'Mark' . PHP_EOL);
check_retval($r);
$r = fwrite($fh, 'Lubos' . PHP_EOL);
check_retval($r);
fclose($fh);
function check_retval($val) {
if ($val === false) {
exit("Cannot write to file\n");
}
}
我们以写入模式打开一个names.txt,并向其中写入四行。
$fh = fopen('names.txt', 'w');
fopen函数以写入模式打开文件。如果该文件不存在,则会自动创建。
$r = fwrite($fh, 'Jane' . PHP_EOL);
使用fwrite函数,我们向文件写入一行。该函数将文件句柄作为其第一个参数。
$ php write_file.php $ cat names.txt Jane Lucy Mark Lubos
我们写入names.txt文件并检查其内容。
我们可以使用高级file_put_contents方法一次性将字符串写入文件。
<?php
$filename = "names.txt";
$buf = file_get_contents($filename);
if ($buf === false) {
exit("Cannot get file contents\n");
}
$buf .= "John\nPaul\nRobert\n";
$r = file_put_contents($filename, $buf);
if ($r === false) {
exit("Cannot write to file\n");
}
在示例中,我们使用file_get_contents函数读取names.txt文件的内容,并使用file_put_contents函数附加新字符串。
PHP可读、可写、可执行文件
is_readable、is_writable和is_executable函数检查文件是否可读、可写和可执行。
<?php
$filename = "myfile.txt";
echo get_current_user() . PHP_EOL;
if (is_readable($filename)) {
echo "The file can be read\n";
} else {
echo "Cannot read file\n";
}
if (is_writable($filename)) {
echo "The file can be written to\n";
} else {
echo "Cannot write to file\n";
}
if (is_executable($filename)) {
echo "The file can be executed\n";
} else {
echo "Cannot execute file\n";
}
我们在myfile.txt文件上运行这三个函数。脚本检查当前用户的这些属性。
$ php rwe.php janbodnar The file can be read The file can be written to Cannot execute file
janbodnar用户可以读取和写入文件,但不能执行该文件。
PHP文件时间
Linux上有三种文件时间:上次访问时间、上次更改时间和上次修改时间。以下PHP函数确定这些时间:fileatime、filectime和filemtime。
<?php
$filename = "myfile.txt";
$atime = fileatime($filename);
$ctime = filectime($filename);
$mtime = filemtime($filename);
echo date("F d, Y H:i:s\n", $atime);
echo date("F d, Y H:i:s\n", $ctime);
echo date("F d, Y H:i:s\n", $mtime);
脚本打印myfile.txt文件的文件时间。
$ php file_times.php April 20, 2016 17:52:54 April 20, 2016 17:53:33 April 20, 2016 17:52:29
这是file_times.php脚本的示例输出。
PHP文件权限
文件系统为不同的用户和用户组强制执行文件权限。fileperms函数获取文件权限;它以数字模式返回文件的权限。
<?php
$perms = fileperms("myfile.txt");
echo decoct($perms & 0777) . PHP_EOL;
$info .= (($perms & 0x0100) ? 'r' : '-');
$info .= (($perms & 0x0080) ? 'w' : '-');
$info .= (($perms & 0x0040) ?
(($perms & 0x0800) ? 's' : 'x' ) :
(($perms & 0x0800) ? 'S' : '-'));
$info .= (($perms & 0x0020) ? 'r' : '-');
$info .= (($perms & 0x0010) ? 'w' : '-');
$info .= (($perms & 0x0008) ?
(($perms & 0x0400) ? 's' : 'x' ) :
(($perms & 0x0400) ? 'S' : '-'));
$info .= (($perms & 0x0004) ? 'r' : '-');
$info .= (($perms & 0x0002) ? 'w' : '-');
$info .= (($perms & 0x0001) ?
(($perms & 0x0200) ? 't' : 'x' ) :
(($perms & 0x0200) ? 'T' : '-'));
echo "$info\n";
脚本决定myfile.txt的文件权限。权限以Unix风格打印到控制台。
echo decoct($perms & 0777) . PHP_EOL;
传统上,Unix上的权限以八进制表示形式编写。decot函数将十进制表示形式转换为八进制形式。
$info .= (($perms & 0x0100) ? 'r' : '-');
在这一行中,我们检查文件权限是否允许文件所有者读取它。
$ php file_permissions.php 660 rw-rw----
这是file_permissions.php脚本的示例输出。
可以使用chmod函数更改文件权限。
<?php
$perms1 = fileperms("myfile.txt");
echo decoct($perms1 & 0777) . PHP_EOL;
$r = chmod("myfile", 0660);
if ($r) {
echo "File mode successfully changed\n";
} else {
exit("Failed to change file mode\n");
}
$perms2 = fileperms("myfile");
echo decoct($perms2 & 0777) . PHP_EOL;
该脚本更改了myfile.txt文件的权限。
$r = chmod("myfile", 0660);
chmod函数在其第二个参数中接受权限作为八进制值。八进制值前面有0。
$ php file_permissions2.php 664 File mode successfully changed 660
文件的权限由664改为660。
PHPCSV文件格式
fgetcsv函数从CSV(逗号分隔值)文件中读取一行;它返回一个包含读取字段的索引数组。fputcsv函数将一行格式化为CSV并将其写入文件。
<?php
$nums = [1, 2, 5, 3, 2, 6, 4, 2, 4,
8, 7, 3, 8, 5, 4, 3];
$fh = fopen('numbers.csv', 'w');
if ($fh === false) {
exit("Failed to open file\n");
}
$r = fputcsv($fh, $nums);
if ($r === false) {
exit("Failed to write values\n");
}
echo "The values have been successfully written\n";
fclose($fh);
此脚本将数组中的数字写入CSV文件。
$ php csv_output.php The values have been successfully written $ cat numbers.csv 1,2,5,3,2,6,4,2,4,8,7,3,8,5,4,3
我们运行脚本并检查文件内容。
在下面的示例中,我们从CSV文件中读取数据。
<?php
$fh = fopen('numbers.csv', 'r');
if ($fh === false) {
exit("Failed to open file\n");
}
while (($data = fgetcsv($fh)) !== false) {
$num = count($data);
for ($i=0; $i < $num; $i++) {
echo "$data[$i] ";
}
}
echo "\n";
fclose($fh);
该脚本使用fgetcsv从numbers.csv文件中读取值并将它们打印到控制台。
$ php csv_input.php 1 2 5 3 2 6 4 2 4 8 7 3 8 5 4 3
这是csv_input.php脚本的输出。
PHP磁盘空间
disk_total_space函数以字节为单位返回文件系统或磁盘分区的总大小,disk_total_space函数以字节为单位返回文件系统或磁盘分区上的可用空间。
<?php
const BYTES_IN_GIGABYTE = 1073741824;
$total_space_bytes = disk_total_space("/");
if ($total_space_bytes === false) {
exit("The disk_total_space() failed\n");
}
$free_space_bytes = disk_free_space("/");
if ($free_space_bytes === false) {
exit("The disk_free_space() failed\n");
}
$total_space_gb = floor($total_space_bytes / BYTES_IN_GIGABYTE);
$free_space_gb = floor($free_space_bytes / BYTES_IN_GIGABYTE);
echo "Total space: $total_space_gb GB\n";
echo "Free space: $free_space_gb GB\n";
该脚本计算根分区上的总空间和可用空间。空间转换为千兆字节。
$ php disk_space.php Total space: 289 GB Free space: 50 GB
这是脚本的示例输出。
在本教程中,我们介绍了PHP文件系统函数。
列出所有PHP教程。
