$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 是追加写入。
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 deprecatedfclose($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, 1423+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