第12 章 目录文件操作
1. 目录
1.1 判断文件类型
可用filetype判断文件类型,语法格式:
string filetype(string $filename)
说明:
- $filename:文件路径,该函数返回的文件类型可能的值为fifo、char、dir、block、link、file和unknown。
- 如果调用失败或者文件类型未知,产生一个E_NOTICE消息
<?php
echo filetype('E:\phpFiles\php01\chapter12\filetype.php'); // file
echo filetype('E:\phpFiles\php01\chapter12'); // dir
?>
除filetype()外,还可以使用is_dir判断文件名是否是一个目录,使用is_file()判断文件名是否为一个正常的文件。
<?php
echo filetype('E:\phpFiles\php01\chapter12\filetype.php'); // file
echo filetype('E:\phpFiles\php01\chapter12'); // dir
var_dump(is_dir('E:\phpFiles\php01\chapter12')); // bool(true)
var_dump(is_file('E:\phpFiles\php01\chapter12\filetype.php')); // bool(true)
var_dump(is_dir('E:\phpFiles\php01\chapter12\filetype.php')); // bool(false)
?>
1.2 创建和删除目录
- 创建目录
在PHP中使用mkdir创建目录,语法如下:
bool mkdir(string $pathname [, int $mode = 0777 [, bool $recursive = false [, resource $context]]])
说明:
- $pathname:待创建的目录
- $mode:默认值为0777(rwx:可读可写可执行,最大访问权)
- $recursive:当值设为true时,允许递归地创建目录
<?php
$structure = "./a/b/c/";
if(!mkdir($structure, 0777, true)) {
die('Failed to create folders...');
} else {
echo "create successfully!";
}
?>
控制台输出:create successfully!
在当前目录下递归地创建/a/b/c/目录。
2. 删除目录
在PHP中使用rmdir删除目录,语法如下:
bool rmdir(string $dirname [, resource $context])
说明:
- $dirname:指定删除的目录。该目录必须是空的(即该目录不能有子目录,也不能包含其他文件),而且要有相应的权限。
- 失败时产生一个E_WARNING级别的错误。
<?php
$structure = './a/b/c/';
if(!rmdir($structure)) {
die('Failed to delete folders...');
} else {
echo "delete successfully!";
}
?>
刚才新建的/a/b/下的c目录被删除。控制台输出:delete successfully!
1.3 打开读取和关闭目录
在PHP中使用opendir()打开目录,语法如下:
resource opendir(string $path [, resource $context])
说明:
- 成功返回目录句柄的resource,失败返回false
- 如果$path不是一个合法的目录或因为权限限制或文件系统错误而不能打开目录,opendir()返回false并产生一个E_WARNING级别的PHP错误信息。
- 可以在opendir()前面加上“@”符号来抑制错误信息的输出。
使用readdir()从目录句柄中读取条目,语法如下:
string readdir([resource $dir_handle])
返回目录中下一个文件的文件名,文件名以在文件系统中的排序返回。
使用closedir()关闭目录句柄,语法如下:
void closedir([resource $dir_handle])
该函数将关闭由dir_handle指定的目录流,且目录流必须之前被opendir()所打开。
<?php
$dir = "./a/b/";
if(is_dir($dir)) {
if($dh = opendir($dir)) {
while(($file = readdir($dh)) !== false) {
echo "filename: $file ; filetype: " . filetype($dir . $file) . "\n";
}
closedir($dh);
}
}
?>
filename: . ; filetype: dir
filename: .. ; filetype: dir
在PHP中使用scandir()列出指定路径中的文件和目录,语法如下:
array scandir(string $directory [, int $sorting_order [, resource $context]])
说明:
- 该函数返回一个包含有$directory中的文件和目录的数组
- $directory:要被浏览的目录
- sorting_order(设为1),排序顺序为按字母降序排列。
<?php
$dir = './';
$files1 = scandir($dir);
$files2 = scandir($dir, 1);
echo "\n";
print_r($files1);
print_r($files2);
?>
Array
(
[0] => chapter01
[1] => .
[2] => ..
[3] => .idea
[4] => a
[5] => chapter02
[6] => chapter03
[7] => chapter04
[8] => chapter05
[9] => chapter06
[10] => chapter08
[11] => chapter09
[12] => chapter10
[13] => chapter11
[14] => chapter12
)
Array
(
[0] => chapter12
[1] => chapter11
[2] => chapter10
[3] => chapter09
[4] => chapter08
[5] => chapter06
[6] => chapter05
[7] => chapter04
[8] => chapter03
[9] => chapter02
[10] => a
[11] => .idea
[12] => ..
[13] => .
[14] => chapter01
)
1.4 获得路径中目录部分
使用dirname()返回路径中的目录部分,语法如下:
string dirname(string $path)
说明:
- 给出一个包含有指向一个文件的全路径字符串,该函数将返回去掉文件名的目录名,即$path的父目录
- 如果在 path中结尾的/component(最后一个斜线以及后面部分)去掉之后的字符串。
- 在Windows中,斜杠和反斜杠(\)都可以用作目录分隔符,在其他环境下是斜杠(/)。
<?php
echo dirname('testDir.php'), "\n";
echo dirname('./a/b/');
?>
.
./a
1.5 目录磁盘空间
- float disk_free_space(string $directory):给出一个包含有一个目录的字符串,该函数将根据相应的文件系统或磁盘分区返回可用的字节数,失败时返回false。
- float disk_total_space(string $directory):给出一个包含有一个目录的字符串。本函数返回的是该目录所在的磁盘分区的总大小,因此将同一个磁盘分区的不同目录作为参数所得到的结果完全相同。
<?php
echo disk_free_space('./a/b/'), "\n"; // 433514803200
echo disk_total_space('/'); // 458071470080
?>
2. 文件操作
2.1 打开文件
PHP中使用fopen()函数打开文件,语法如下:
resource fopen(string $filename, string $mode [, bool $use_include_path = false [, resource $context]])
说明:
- $filename:文件路径
- $mode:打开文件的模式
2.2 读取文件
- fgets()
fgets()从文件指针中读取一行,语法如下:
string fgets(resource $handle [, int $length])
说明:
- $handle:用fopen()打开的文件句柄
- $length:从 length-1字节的字符串。
- 碰到换行符(包括在返回值中)、EOF或者已经读取了$length-1字节后停止
- 如果没有指定$length,默认为1KB,或1024字节
fgets.php
<?php
$handle = fopen('chapter12/test.txt', 'r');
if($handle) {
while (($buffer = fgets($handle, 4096)) !== false) {
echo $buffer;
}
if(!feof($handle)) {
echo "Error: unexpected fgets() fail\n";
}
fclose($handle);
}
?>
test.txt:
abcdef
ghijk
java
php
language
输出:
abcdef
ghijk
java
php
language
- fgetc()
fgetc()可从文件指针中读取字符,语法如下:
string fgetc(resource $handle)
说明:
- $handle文件指针必须是有效的,必须指向由fopen()或fsockopen()成功打开的文件(还未由fclose()关闭)
- 该函数返回一个包含有一个字符的字符串,这个字符从$handle指向的文件中得到。若遇到EOF则返回false。
<?php
$fp = fopen('chapter12/test.txt', 'r');
if(!$fp) {
echo 'Could not open file somefile.txt';
}
while(false !== ($char = fgetc($fp))) {
echo "$char\n";
}
?>
a
b
c
d
e
f
g
h
i
j
k
j
a
v
a
p
h
p
l
a
n
g
u
a
g
e
2.3 获得文件属性
文件属性包括文件的上次访问修改时间、文件大小类型等信息。
- fileatime():获取文件上次访问的时间
- filemtime():获取文件修改的时间
- filesize():获取文件大小
- filetype():获取文件类型
- stat():返回文件信息(上次访问、修改时间及文件大小等)
<?php
$filename = 'E:\phpFiles\php01\chapter12\\test.txt';
if(file_exists($filename)) {
echo "上一次访问 $filename 的时间是:". date('Y-m-d H:i:s', fileatime($filename)), "\n";
// 上一次访问 E:\phpFiles\php01\chapter12\test.txt 的时间是:2020-06-13 15:09:25
echo "上一次修改 $filename 的时间为:". date('Y-m-d H:i:s', filemtime($filename)), "\n";
// 上一次修改 E:\phpFiles\php01\chapter12\test.txt 的时间为:2020-06-13 14:59:30
echo $filename . ": ". filesize($filename) .' bytes.', "\n";
echo filetype($filename), "\n";
print_r(stat($filename));
}
上一次访问 E:\phpFiles\php01\chapter12\test.txt 的时间是:2020-06-13 15:09:25
上一次修改 E:\phpFiles\php01\chapter12\test.txt 的时间为:2020-06-13 14:59:30
E:\phpFiles\php01\chapter12\test.txt: 34 bytes.
file
Array
(
[0] => 3029726606
[1] => 3096224744005234
[2] => 33206
[3] => 1
[4] => 0
[5] => 0
[6] => 0
[7] => 34
[8] => 1592060965
[9] => 1592060370
[10] => 1592059385
[11] => -1
[12] => -1
[dev] => 3029726606
[ino] => 3096224744005234
[mode] => 33206
[nlink] => 1
[uid] => 0
[gid] => 0
[rdev] => 0
[size] => 34
[atime] => 1592060965
[mtime] => 1592060370
[ctime] => 1592059385
[blksize] => -1
[blocks] => -1
)
2.4 复制/删除/移动/重命名文件
- 复制文件:bool copy(string $source, string $dest[, resouce $context])
- 删除文件:bool unlink(string $filename [, resource $context])
- 移动/重命名文件:bool rename(string $oldname, string $newname [, resource $context])
<?php
$file = 'E:\phpFiles\php01\chapter12\\test.txt';
$newfile = 'E:\phpFiles\php01\chapter12\\test.txt.bak';
/**
* 复制文件
*/
if(!copy($file, $newfile)) {
echo "failed to copy $file...\n";
} else {
echo "copy successfully!","\n";
}
/**
* 删除文件
*/
if(!unlink($newfile)) {
echo "failed to delete $file...\n";
} else {
echo "delete successfully!\n";
}
/**
* 重命名
*/
if(rename('E:\phpFiles\php01\chapter12\\test.txt', 'E:\phpFiles\php01\chapter12\\test2.txt')) {
echo "success!\n";
} else {
echo "failed!\n";
}
/**
* 移动并重命名
*/
if(rename('E:\phpFiles\php01\chapter12\\test2.txt', 'E:\phpFiles\php01\chapter11\\test.txt')) {
echo "success!\n";
} else {
echo "failed!\n";
}
?>
3. 文件指针
PHP可以实现文件指针的定位及查询,从而实现所需信息的快速查询。指针的位置是从文件头部开始的字节数,默认的文件指针通常存在于文件头或结尾,可通过PHP提供的fseek()、feof()和ftell()等函数对指针位置进行操作。
- rewind()
倒回文件指针的位置,语法如下:
bool rewind(resource $handle)
其作用是将$handle的文件位置指针设为文件流的开头。
2. fseek()
在文件指针中定位
3. ftell()
返回文件指针读写的位置
<?php
$filename = "E:\phpFiles\php01\chapter12\\1.txt";
if(is_file($filename)) {
echo "文件总字节数:" . filesize($filename) . "\n";
$fopen = fopen($filename, "rb");
echo "初始指针位置:" . ftell($fopen), "\n";
fseek($fopen, 5);
echo "使用fseek()函数后指针位置为:" . ftell($fopen) . "\n";
// 当前指针后面的内容从5开始,fgets()函数输出5以后的内容
echo "输出当前指针后面的内容:" . fgets($fopen), "\n";
if (feof($fopen)) {
// 当前指针指向文件末尾时,指针的位置等于文件的总字节数
echo "当前指针指向文件末尾:" . ftell($fopen) . "\n";
}
rewind($fopen);
echo "使用rewind()函数后指针的位置:".ftell($fopen),"\n";
/**
* fgets()函数执行成功时从参数$handle指向的文件中读取一行,
* 并返回长度最多为$length -1 字节的字符串,因此设置为6时,可以输出前5个字节的内容
*/
echo "输出前5个字节的内容:" . fgets($fopen, 6);
fclose($fopen); // fclose()函数
}
else {
echo "文件不存在!";
}
?>
文件总字节数:26
初始指针位置:0
使用fseek()函数后指针位置为:5
输出当前指针后面的内容:fghijklmnopqrstuvwxyz
当前指针指向文件末尾:26
使用rewind()函数后指针的位置:0
输出前5个字节的内容:abcde
4. 文件上传
上传文件需要配置php.ini中的参数。