7/26/2017 PM
PHP文件处理
将数据写入一个文件分三步:
- 打开这个文件(不存在就创建这个文件);
- 将数据写入;
- 关闭这个文件。
将数据从一个文件读出来也分三步:
- 打开这个文件(不存在就关闭文件停止读取);
- 将数据读出;
- 关闭这个文件。
接下来我就分文件的打开、读写、关闭、常见问题来总结一下这方面的学习成果。
打开文件 fopen()
先给出官方文档
resource fopen ( string $filename , string $mode [, bool $use_include_path = false [, resource $context ]] )
fopen有两个必选参量,两个可选参量。必选的为
string filename——文件名(包含地址)string mode——设置文件模式
这里先说一下文件模式,文件模式是对此次打开文件所进行的操作的控制与限制,通过文件模式控制此次操作文件时操作者所拥有的权限以及对文件进行什么样的操作。具体的文件模式有:
r ——只读,从开头开始读。
r+ ——读写,从开头开始读与写。
w ——只写,若有同名文件就清空内容再写入,若没有就创建文件再写入。
w+ ——读写,写时与 w 相同,读时会先将文件清空。
a ——追写,与 w 相比较只有一点不同,就是当有同名文件时不会清空内容,会在文件尾处追写。
a+ ——追读写,写时与a相同,读时与 r 相同。
x ——谨慎写,若有同名文件就停止操作并返回一个警告,若无则同w。
x+ ——谨慎读写,写时同 x ,读时同 r 。
以上6个是对文件的操作方面的限制与规定,还有两种对文件展示形式的规定。
b ——二进制模式。
t ——文本模式。
操作方面的规定与展示形式方面的规定可组合使用,如“rb”就表示以二进制的方式只读。
fopen的两个可选参量为:
bool useincludepath是否使用includepath,类似环境变量的东西,可以在php里用setincludepath()设置,也可以写php.ini里面resource context 上下文,貌似涉及到文件流等操作,小白我还没搞懂,明天研究研究。
读取文件
主要用到fread(),file_get_contents(),file(),fgets()这四个函数读取文件信息,不多说直接上代码。
<?php
/**
* Created by PhpStorm.
* User: nassir
* Date: 2017/7/26
* Time: 9:34
*/
$name = $_FILES["file_name"]["name"];
$tmp = $_FILES["file_name"]["tmp_name"];
//1.1 用fread函数整体读取
function rf_fread (string $address)
{
// 打开文件
$handle = fopen($address,"rt");
// filesize()获取文件内容长度,然后整体读取
$content = fread($handle, filesize($address));
// 检验是否读取成功,再把文件中的换行符用<br>代替方便前端显示
if (!$content) {
return "failed";
}
$content = str_replace("\r\n", "<br>", $content);
fclose($handle);
return $content;
}
//1.2 用fread函数分字节读取
function rf_fread_b ($address)
{
// 打开文件
$handle = fopen($address,"rt");
// 定义每次读取多少字节
$buffer = 512;
// 内容初始化
$content = "";
// 分字节读取并将读取内容追加到content中
while (!feof($handle)) {
$content .= fread($handle, $buffer);
}
// 检验是否读取成功,再把文件中的换行符用<br>代替方便前端显示
if (!$content) {
return "failed";
}
$content = str_replace("\r\n", "<br>", $content);
fclose($handle);
return $content;
}
//2 用file_get_contents()获取全文
function rf_get_cont ($address)
{
// 打开文件
$handle = fopen($address,"rt");
// 获取全文
$content = file_get_contents($address);
// 检验是否读取成功,再把文件中的换行符用<br>代替方便前端显示
if (!$content) {
return "failed";
}
$content = str_replace("\r\n", "<br>", $content);
fclose($handle);
return $content;
}
//3 用file函数获取全文
function fr_file ($address)
{
// 打开文件
$handle = fopen($address,"rt");
// 内容初始化
$content = "";
// 获取全文
$file_arr = file($address);
if (!$file_arr) {
return "failed";
}
foreach ($file_arr as $file_line) {
$content .= $file_line;
}
// 检验是否读取成功,再把文件中的换行符用<br>代替方便前端显示
if (!$content) {
return "failed";
}
$content = str_replace("\r\n", "<br>", $content);
fclose($handle);
return $content;
}
//4 使用fget从文件指针中一行一行读出全文
function rf_fgets ($address)
{
// 打开文件
$handle = fopen($address,"rt");
// 获取全文
$content = "";
while(!feof($handle)){
$content .= fgets($handle);
}
// 检验是否读取成功,再把文件中的换行符用<br>代替方便前端显示
if (!$content) {
return "failed";
}
$content = str_replace("\r\n", "<br>", $content);
fclose($handle);
return $content;
}
//调用
echo "rf_fread : <br>" . rf_fread($tmp) . "<br>";
echo "rf_fread_b : <br>" . rf_fread_b($tmp) . "<br>";
echo "rf_get_cont : <br>" . rf_get_cont($tmp) . "<br>";
echo "fr_file : <br>" . fr_file($tmp) . "<br>";
echo "rf_fgets : <br>" . rf_fgets($tmp) . "<br>";
前端结果为:
rf_fread :
这是第一行 this is the first line
这是第二行 this is the second line
这是第三行 this is the third line
这是结尾 th end
rf_fread_b :
这是第一行 this is the first line
这是第二行 this is the second line
这是第三行 this is the third line
这是结尾 th end
rf_get_cont :
这是第一行 this is the first line
这是第二行 this is the second line
这是第三行 this is the third line
这是结尾 th end
fr_file :
这是第一行 this is the first line
这是第二行 this is the second line
这是第三行 this is the third line
这是结尾 th end
rf_fgets :
这是第一行 this is the first line
这是第二行 this is the second line
这是第三行 this is the third line
这是结尾 th end
写入文件
我只学了两种写入文件的方法fwrite(),file_put_contents()。
前一个是最基础的写入函数,后一个更像是fopen(),fwrite(),fclose()三合一版本。不多说直接放代码吧。
//写入
function wf_fwrite ($address, $content)
{
// 打开要写入的文件
$handle = fopen($address, "at");
// 写入,并返回结果
echo fwrite($handle, $content);
// 关闭文件
fclose($handle);
}
function wf_file_put_contents ($address, $content)
{
// 写入,并返回结果
echo file_put_contents($address, $content);
}
var_dump(rf_fread($tmp));
//wf_fwrite("../uploads/writefile.txt", rf_fread($tmp));
wf_file_put_contents("../uploads/writefile.txt", rf_fread($tmp));
其他函数
- 检测文件存在:file_exists();
- 文件大小:filesize();
- 文件删除:unlink();
- 文件指针定位:rewind(),fseek(),ftell();
文件锁定
文件锁定用到的函数是flock(),官方文档如下:
bool flock ( resource $handle , int $operation [, int &$wouldblock ] )
$handle为要锁定的文档,$operation为要进行合作类型的锁定。
先说一下锁定的意义,再说一下有哪些锁定的类型。锁定主要是为了防止不同用户在对同一文件进行操作时互相干扰的情况发生,比如一个用户要把数据写入文件A,而另一个用户要从文件A读取数据,这样写入的操作就很可能会干扰到读取数据的操作。
flock()的$operation有4个操作值,如下:
LOCK_SH 读操作锁定,文件共享读权限,但不可写;
LOCK_EX 写操作锁定,文件不可被共享;
LOCK_UN 解锁;
LOCK_NB 防止加锁时发生阻塞。
拿之前的写入方法wf_fwrite()举例,重写该方法:
//写入
function wf_fwrite ($address, $content)
{
// 打开要写入的文件
$handle = fopen($address, "at");
// 加锁
flock($handle, LOCK_EX);
// 写入,并返回结果
echo fwrite($handle, $content);
// 解锁
flock($handle, LOCK_UN);
// 关闭文件
fclose($handle);
}
常见问题
- 打开文件时的问题以及注意事项
- 地址中注意符号问题;
- 文件模式遵从权限最小原则;
- 读时注意的问题
- 注意编码格式,不同系统间穿文件时可能会出现各种各样的字符编码问题,最好用统一的UTF-8无BOM编码;
- 注意不同系统间的差异,比如换行在window是
'\r\n'
在Linux是'\b'
在Mac是'\r'
。
- 写时注意的问题
- 在服务器端的权限问题,这个务必重视;
- 写入文件的路径问题,想到离开服务器目录的路径是需要另行设置的;
- 关闭文件时注意的问题
- 没什么问题。。。记着关上文件就行了。