总算来到咱们最关怀的局部了,也就是 f 相干函数的操作。基本上大部分的文件操作都是以明天学习的这些内容为根底的,话不多说,咱们就一个一个的来学习学习吧。
文件读取
文件的读取其实非常简单,fopen() 关上句柄,fread() 读取内容,fclose() 敞开句柄,一套流程下来操作就实现了。
$f = fopen('./test.txt', 'r+');
while (!feof($f)) {$contents = fread($f, 4);
echo $contents, PHP_EOL;
}
// Rain
// is
// fall
// ing
// all
// arou
// nd,
// It f
// alls
// on
// ……
// ……
fopen() 函数的第二个参数是咱们能够操作的权限。这个大家应该不会生疏,w 就是可写,r 就是可读,r+ 就是读写形式关上并将文件指针指向文件头,a 是追加写入。
模式 | 阐明 | |
---|---|---|
‘r’ | 只读形式关上,将文件指针指向文件头。 | |
‘r+’ | 读写形式关上,将文件指针指向文件头。 | |
‘w’ | 写入形式关上,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创立之。 | |
‘w+’ | 读写形式关上,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创立之。 | |
‘a’ | 写入形式关上,将文件指针指向文件开端。如果文件不存在则尝试创立之。 | |
‘a+’ | 读写形式关上,将文件指针指向文件开端。如果文件不存在则尝试创立之。 | |
‘x’ | 创立并以写入形式关上,将文件指针指向文件头。如果文件已存在,则 fopen() 调用失败并返回 FALSE,并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创立之。这和给 底层的 open(2) 零碎调用指定 O_EXCL | O_CREAT 标记是等价的。 |
‘x+’ | 创立并以读写形式关上,其余的行为和 ‘x’ 一样。 | |
‘c’ | 只关上文件进行写入。如果文件不存在,则创立该文件。如果它存在,它既不会被截断(与“w”相同),也不会导致对该函数的调用失败(与“x”一样) | |
‘c+’ | 关上文件进行读写;否则它的行为与“c”雷同。 |
fread() 函数的第二个参数是每次要读取的字节数,能够看到在测试代码中咱们是以 4 个字节为单位进行读取的,所以文件内容都是按 4 个字节离开的一行一行的输入的。feof() 用于判断以后文件的游标指针是否曾经挪动到开端了。
游标操作
既然说到游标,那么咱们就来看看游标相干的操作。
while (!feof($f)) {$contents = fread($f, 1024);
echo $contents, PHP_EOL;
}
//
rewind($f);
while (!feof($f)) {$contents = fread($f, 1024);
echo $contents, PHP_EOL;
}
// Rain is falling all around,
// It falls on field and tree,
// It rains on the umbrella here,
// And on the ships at sea.
当应用最上方的代码读取过一遍内容后,游标就曾经到底了,这时候再次循环是无奈读取文件内容的,须要应用 rewind() 函数将游标进行重置。
读取单个字符
rewind($f);
while (($c = fgetc($f)) !== false) {echo $c, PHP_EOL;}
// R
// a
// i
// n
// i
// s
// f
// a
// ……
// ……
fgetc() 函数用于读取单个字符。这个函数就比较简单了,不过须要留神的是如果用它读取中文的话,成果就不行了,因为中文是一个字占 2 或 3 个字节,应用这个函数读取进去的将是乱码的内容,在前面咱们会有示例。
读取一行
while (($c = fgets($f)) !== false) {echo $c, PHP_EOL;}
// Rain is falling all around,
// It falls on field and tree,
// It rains on the umbrella here,
// And on the ships at sea.
fgets() 函数用于按行读取文件内容,这个函数也是比拟罕用的函数,大家不会生疏。
读取 csv 文件
// fgetcsv
$f = fopen('./csv_test.csv', 'r');
while (($c = fgetcsv($f)) !== false) {print_r($c);
}
// Array
// (// [0] => 49
// [1] => 20
// [2] => 0
// [3] => 42
// [4] => 5/10/2020 12:32:18
// )
// Array
// (// [0] => 50
// [1] => 21
// [2] => 0
// [3] => 74
// [4] => 5/10/2020 12:32:29
// )
// Array
// (// [0] => 51
// [1] => 22
// [2] => 0
// [3] => 35.8
// [4] => 5/10/2020 12:32:38
// )
// ……
// ……
fclose($f);
对于 CSV 是什么文件这里就不多做解释了,笔者毕业时的第一个我的项目中就有很多操作 CSV 文件的小性能,也能够说,这个 fgetcsv() 函数是笔者对于文件操作的启蒙函数。它能够不便地按行读取 CSV,并将它们解析成数组格局不便咱们地操作。不过个别如果是 Excel 文件转换过去的内容,咱们都会将第一行题目行排除掉,当然,这个就是依据业务开发的理论状况来说啦。
读取过滤 HTML
// fgetss
$f = fopen('./html_test.txt', 'r');
while (($c = fgetss($f)) !== false) {echo $c, PHP_EOL;}
// PHP Deprecated: Function fgetss() is deprecated
fclose($f);
fgetss() 函数在读取文件的时候能够过滤掉 HTML 代码,不过这个函数曾经废除了。
中文读取问题
对于中文的读取来说,咱们最次要关怀的就是中文字符和英文字符所占字节的区别问题,下面曾经说过了,中文如果是 UTF8 编码格局,将占用 3 个字节,如果是 GBK 之类的将占用 2 个字节。所以如果咱们应用 fread() 时,要应用对应编码的倍数来读取,比方上面咱们的测试文件是 UTF8 编码的,须要按三个字符的形式读取,就须要传递参数为 6。
// 中文测试
$f = fopen('./cn_test.txt', 'r+');
while (!feof($f)) {$contents = fread($f, 6);
echo $contents, PHP_EOL;
}
// 我本
// 有为
// 野客
//,飘
// 飘浪
// 迹人
// 间。// 一�
// �被�
// ……
// ……
while (!feof($f)) {$contents = fread($f, 1024);
echo $contents, PHP_EOL;
}
//
rewind($f);
while (!feof($f)) {$contents = fread($f, 1024);
echo $contents, PHP_EOL;
}
// 我本有为野客,飘飘浪迹世间。// 一时被命住名山。未免随机应变。// 识破尘劳扰扰,何如乐取安闲。// 流霞细酌咏诗篇。且与白云为伴。rewind($f);
while (($c = fgetc($f)) !== false) {echo $c, PHP_EOL;}
// �
// �
// �
// ……
// ……
rewind($f);
while (($c = fgets($f)) !== false) {echo $c, PHP_EOL;}
// 我本有为野客,飘飘浪迹世间。// 一时被命住名山。未免随机应变。// 识破尘劳扰扰,何如乐取安闲。// 流霞细酌咏诗篇。且与白云为伴。fclose($f);
fread() 函数读取的内容两头为什么还会呈现乱码呢?因为咱们的换行符还是按英文码只占一个字节的呀!另外,fgetc() 函数就比拟惨了,fgets() 函数还是可能失常地读取地。
读取残余内容
$f = fopen('./cn_test.txt', 'r+');
echo fgets($f), PHP_EOL;
// 我本有为野客,飘飘浪迹世间。echo fpassthru($f), PHP_EOL;
// 一时被命住名山。未免随机应变。// 识破尘劳扰扰,何如乐取安闲。// 流霞细酌咏诗篇。且与白云为伴。rewind($f);
在这段测试代码中,咱们应用 fgets() 读取了一行内容,而后再应用 fpassthru() 间接就将文件中残余的内容全副读取进去了。这就是 fpassthru() 函数的作用,它能够将文件中游标之后全副残余的内容读取进去。
fseek($f, 3 * 14 + 1);
echo fgets($f), PHP_EOL;
// 一时被命住名山。未免随机应变。
另外还有一个 fseek() 函数,能够指定以后从哪个地位开始读取,能够将它也看做是游标操作的一部分。
rewind($f);
fseek($f, 14 * 2 * 3 + 1);
echo ftell($f), PHP_EOL; // 85
ftell() 函数则是返回的文件残余的字节信息。
文件句柄信息
print_r(fstat($f));
// Array
// (// [0] => 16777220
// [1] => 8708492112
// [2] => 33188
// [3] => 1
// [4] => 501
// [5] => 20
// [6] => 0
// [7] => 177
// [8] => 1603414680
// [9] => 1603414679
// [10] => 1603414679
// [11] => 4096
// [12] => 8
// [dev] => 16777220
// [ino] => 8708492112
// [mode] => 33188
// [nlink] => 1
// [uid] => 501
// [gid] => 20
// [rdev] => 0
// [size] => 177
// [atime] => 1603414680
// [mtime] => 1603414679
// [ctime] => 1603414679
// [blksize] => 4096
// [blocks] => 8
// )
fstat() 函数和之前文章中咱们讲过的 stat() 函数的性能是一样的,只不过它须要的是一个句柄参数,而后返回这个句柄对应文件的信息。而 stat() 间接给的是文件的门路。
文件截断
// 文件会变
ftruncate($f, 14*2*3+4);
echo fread($f, 8094), PHP_EOL;
// 我本有为野客,飘飘浪迹世间。// 一时被命住名山。未免随机应变。fclose($f);
ftruncate() 函数会从指定的地位截断文件内容。在这里咱们只保留了前两行的内容,前面的内容就被截断掉了。应用这个函数须要留神的是,它会扭转原有文件的内容。
读取文件并从格式化输出
$f = fopen("users_test.txt", "r");
while ($userinfo = fscanf($f, "%s\t%s\t%s\n")) {print_r($userinfo);
}
// Array
// (// [0] => javier
// [1] => argonaut
// [2] => pe
// )
// Array
// (// [0] => hiroshi
// [1] => sculptor
// [2] => jp
// )
// Array
// (// [0] => robert
// [1] => slacker
// [2] => us
// )
// Array
// (// [0] => luigi
// [1] => florist
// [2] => it
// )
fclose($f);
fscanf() 函数会依据第二个参数传递的内容来格式化文件的内容。就像会用 printf() 函数一样,只不过它是从读取的角度来取得数据内容。这里会将制表符作为分隔来造成格式化的后果数组。
文件内容匹配
var_dump(fnmatch('*fall[ing]*', file_get_contents('./test.txt'))); // bool(true)
fnmatch() 函数用于判断给定的内容中是否蕴含第一个参数中指定的规定。它有点像正则表达式相干的函数的用法,而且并不是操作文件的,是针对字符串的。不过它的规定定义是以 Linux 零碎中的文件操作匹配规定为准的,也就是说它不是齐全的正则规定。就像咱们常常在 Linux 中查看某个文件的信息:ll *.txt 这样。
过程文件读取操作
这个是什么意思呢?其实就是咱们能够执行一段操作系统的过程代码,而后取得它的后果,这个流会以文件流的模式返回给 PHP 造成一个文件流句柄。
$handle = popen("/bin/ls", "r");
while(!feof($handle)){echo fgets($handle);
}
pclose($handle);
// 1.PHP 中的日期相干函数(三).php
// 2. 学习 PHP 中的目录操作.php
// 3. 学习 PHP 中的高精度计时器 HRTime 扩大.php
// 4.PHP 中 DirectIO 直操作文件扩大的应用.php
// 5. 学习 PHP 中 Fileinfo 扩大的应用.php
// 6.PHP 中的文件系统函数(一).php
// 7.PHP 中的文件系统函数(二).php
// 8.PHP 中的文件系统函数(三).php
// cn_test.txt
// csv_test.csv
// html_test.txt
// test.txt
// timg.jpeg
// users_test.txt
// write.txt
文件写入
文件写入就比较简单了,就这么一点代码的介绍。而且也就三个函数。
// 写入
$f = fopen('write.txt', 'w');
fwrite($f, "This is Test!\n");
fputs($f, "This is Test2!!\n");
$csv = [['id', 'name'],[1, 'Zyblog'], [2, '硬核项目经理']];
foreach($csv as $v){fputcsv($f, $v);
}
fclose($f);
// This is Test!
// This is Test2!!
// id,name
// 1,Zyblog
// 2, 硬核项目经理
fwrite() 用于向文件句柄中写入内容。fputs() 是 fwrite() 的别名,它们两个是一个货色。fputcsv() 函数则是以 CSV 的格局将数组内容写入到文件中,它还有其它的参数能够批改分隔符具体应用哪个符号,在这里咱们默认就是逗号。
文件加锁
$fp = fopen("/tmp/lock.txt", "w+");
if (flock($fp, LOCK_EX)) { // 进行排它型锁定
fwrite($fp, "写入数据:" . date('H:i:s') . "\n");
if(!$argv[1]){sleep(50);
}
fflush($fp); // 开释锁之前刷新缓冲区
flock($fp, LOCK_UN); // 开释锁定
} else {echo "无奈取得锁,不能写入!";}
fclose($fp);
锁定一个文件,而后其它的操作就不能读取它了,这种操作个别在多线程或者多个性能会同时操作一个文件时会十分罕用。flock() 的第二个参数能够设置读锁、写锁等,这里咱们应用的是 LOCK_EX 共享排它锁,也就是一个写锁。当咱们运行这段代码后,在停留的工夫内容,其它的脚本是无奈写入数据的,如果有同时操作这个文件的脚本在运行也会卡在这里直到这边的锁开释掉。
- LOCK_SH 获得共享锁定(读取的程序)。
- LOCK_EX 获得独占锁定(写入的程序。
- LOCK_UN 开释锁定(无论共享或独占)。
- 如果不心愿 flock() 在锁定时梗塞,则是 LOCK_NB(Windows 上还不反对)。
fflush() 用于刷新缓冲区,这个也是之前讲过的对于 PHP 中缓冲区相干的常识,大家能够回去复习一下,PHP 中的输入缓冲管制。在文件操作中,应用这个函数就能马上刷新缓冲区的内容并将内容写入到具体的文件中。
总结
是不是很嗨,一下子学习了这么多函数。这篇文章完结也就是 PHP 原生的这些文件操作函数就学习完了。当然,理解只是一方面,更多的还是要多多尝试利用到本人的我的项目中。
测试代码:
https://github.com/zhangyue0503/dev-blog/blob/master/php/202010/source/8.PHP 中的文件系统函数(三).php
参考文档:
https://www.php.net/manual/zh/ref.filesystem.php
各自媒体平台均可搜寻【硬核项目经理】