在本文中,我们介绍了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教程。