PHP中的文件系统函数(三)
liebian365 2024-11-21 17:35 3 浏览 0 评论
总算来到我们最关心的部分了,也就是 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 |
'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
参考文档:
相关推荐
- 快递查询教程,批量查询物流,一键管理快递
-
作为商家,每天需要查询许许多多的快递单号,面对不同的快递公司,有没有简单一点的物流查询方法呢?小编的回答当然是有的,下面随小编一起来试试这个新技巧。需要哪些工具?安装一个快递批量查询高手快递单号怎么快...
- 一键自动查询所有快递的物流信息 支持圆通、韵达等多家快递
-
对于各位商家来说拥有一个好的快递软件,能够有效的提高自己的工作效率,在管理快递单号的时候都需要对单号进行表格整理,那怎么样能够快速的查询所有单号信息,并自动生成表格呢?1、其实方法很简单,我们不需要一...
- 快递查询单号查询,怎么查物流到哪了
-
输入单号怎么查快递到哪里去了呢?今天小编给大家分享一个新的技巧,它支持多家快递,一次能查询多个单号物流,还可对查询到的物流进行分析、筛选以及导出,下面一起来试试。需要哪些工具?安装一个快递批量查询高手...
- 3分钟查询物流,教你一键批量查询全部物流信息
-
很多朋友在问,如何在短时间内把单号的物流信息查询出来,查询完成后筛选已签收件、筛选未签收件,今天小编就分享一款物流查询神器,感兴趣的朋友接着往下看。第一步,运行【快递批量查询高手】在主界面中点击【添...
- 快递单号查询,一次性查询全部物流信息
-
现在各种快递的查询方式,各有各的好,各有各的劣,总的来说,还是有比较方便的。今天小编就给大家分享一个新的技巧,支持多家快递,一次能查询多个单号的物流,还能对查询到的物流进行分析、筛选以及导出,下面一起...
- 快递查询工具,批量查询多个快递快递单号的物流状态、签收时间
-
最近有朋友在问,怎么快速查询单号的物流信息呢?除了官网,还有没有更简单的方法呢?小编的回答当然是有的,下面一起来看看。需要哪些工具?安装一个快递批量查询高手多个京东的快递单号怎么快速查询?进入快递批量...
- 快递查询软件,自动识别查询快递单号查询方法
-
当你拥有多个快递单号的时候,该如何快速查询物流信息?比如单号没有快递公司时,又该如何自动识别再去查询呢?不知道如何操作的宝贝们,下面随小编一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号若干...
- 教你怎样查询快递查询单号并保存物流信息
-
商家发货,快递揽收后,一般会直接手动复制到官网上一个个查询物流,那么久而久之,就会觉得查询变得特别繁琐,今天小编给大家分享一个新的技巧,下面一起来试试。教程之前,我们来预览一下用快递批量查询高手...
- 简单几步骤查询所有快递物流信息
-
在高峰期订单量大的时候,可能需要一双手当十双手去查询快递物流,但是由于逐一去查询,效率极低,追踪困难。那么今天小编给大家分享一个新的技巧,一次能查询多个快递单号的物流,下面一起来学习一下,希望能给大家...
- 物流单号查询,如何查询快递信息,按最后更新时间搜索需要的单号
-
最近有很多朋友在问,如何通过快递单号查询物流信息,并按最后更新时间搜索出需要的单号呢?下面随小编一起来试试吧。需要哪些工具?安装一个快递批量查询高手快递单号若干怎么快速查询?运行【快递批量查询高手】...
- 连续保存新单号功能解析,导入单号查询并自动识别批量查快递信息
-
快递查询已经成为我们日常生活中不可或缺的一部分。然而,面对海量的快递单号,如何高效、准确地查询每一个快递的物流信息,成为了许多人头疼的问题。幸运的是,随着科技的进步,一款名为“快递批量查询高手”的软件...
- 快递查询教程,快递单号查询,筛选更新量为1的单号
-
最近有很多朋友在问,怎么快速查询快递单号的物流,并筛选出更新量为1的单号呢?今天小编给大家分享一个新方法,一起来试试吧。需要哪些工具?安装一个快递批量查询高手多个快递单号怎么快速查询?运行【快递批量查...
- 掌握批量查询快递动态的技巧,一键查找无信息记录的两种方法解析
-
在快节奏的商业环境中,高效的物流查询是确保业务顺畅运行的关键。作为快递查询达人,我深知时间的宝贵,因此,今天我将向大家介绍一款强大的工具——快递批量查询高手软件。这款软件能够帮助你批量查询快递动态,一...
- 从复杂到简单的单号查询,一键清除单号中的符号并批量查快递信息
-
在繁忙的商务与日常生活中,快递查询已成为不可或缺的一环。然而,面对海量的单号,逐一查询不仅耗时费力,还容易出错。现在,有了快递批量查询高手软件,一切变得简单明了。只需一键,即可搞定单号查询,一键处理单...
- 物流单号查询,在哪里查询快递
-
如果在快递单号多的情况,你还在一个个复制粘贴到官网上手动查询,是一件非常麻烦的事情。于是乎今天小编给大家分享一个新的技巧,下面一起来试试。需要哪些工具?安装一个快递批量查询高手快递单号怎么快速查询?...
你 发表评论:
欢迎- 一周热门
- 最近发表
- 标签列表
-
- wireshark怎么抓包 (75)
- qt sleep (64)
- cs1.6指令代码大全 (55)
- factory-method (60)
- sqlite3_bind_blob (52)
- hibernate update (63)
- c++ base64 (70)
- nc 命令 (52)
- wm_close (51)
- epollin (51)
- sqlca.sqlcode (57)
- lua ipairs (60)
- tv_usec (64)
- 命令行进入文件夹 (53)
- postgresql array (57)
- statfs函数 (57)
- .project文件 (54)
- lua require (56)
- for_each (67)
- c#工厂模式 (57)
- wxsqlite3 (66)
- dmesg -c (58)
- fopen参数 (53)
- tar -zxvf -c (55)
- 速递查询 (52)