读w3c文件部分和一些博客之后,记录个人认为的可能比较常用的函数。
打开文件(创建)
通过fopen($filename, $mode, $use_include_path = null, $context = null)
打开文件,成功则返回文件句柄handle,$mode的值有如下4组:
- r/r+,分别对应只读/读写,文件指针在开头,如果文件存在,不会清空该文件(r+),如文件不存在,不会创建该文件
- w/w+,分别对应只写/读写,如果文件存在,则清空文件,如果文件不存在,则创建该文件,文件指针在开头
- a/a+,分别对应只写/读写,如果文件存在,保留文件内容,文件指针在结尾,如果文件不存在,新建该文件
- x/x+,分别对应创建只读文件/读写文件,如果文件已存在,则失败。
以上提到的如果文件不存在自动穿件的情况有一个前提:目标文件的所在父级目录要存在。
文件读取
fread ($handle, $length)
读取至指定字节长度的内容1
2
3$full_file_name = dirname(__FILE__) . '/1.txt';
$handle = fopen($full_file_name, 'r');
echo fread($handle, filesize($full_file_name));file_get_contents ($filename, $use_include_path = false, $context = null, $offset = 0, $maxlen = null) {}
从指定字节开始(默认0)读取指定字节长度的内容(默认全部)到一个字符串中。文件中的换行标识为\n(mac/linux是\n,window是\r\n),而html的换是<br>,所以读取的内容换行没了。解决方案是使用<pre>原格式输出,或者把\n换成<br>(注意替换的时候,“\n”双引号,单引号不起作用)。如果两个字符之间有多个空格,则读取的内容中只有一个空格,替换字符串的“ ”(中间有一个空格)替换为 (使用频率最高,适用于小文件读取,大文件的话,参考下面优化的)fgets($handle)
按行读取内容,每读取一行,文件指针下移一行,直到feof($handle) = true
,空格不显示问题,参考2fgetc($handle)
按字节读取,每读取一个字节,文件指针下移一个字节,直到feof($handle) = true
parse_ini_file($filename)
项目中存在各种各样的配置文件(xxxconfig.ini),其文件内容格式如下该函数将如上内容的每一项包装成key=>value,然后以数组形式返回。dbconfig.ini 1
2
3
4server=11.111.11.11
username=zwk
psw=admin
port=3306
一点可以优化的地方,未必每次都是需要一次性将整个文件读到内存进行操作,利用其中的读取范围的参数,一部分一部分读取处理。1
2
3
4
5
6
7$buffer = '';
$size = 1024;
while (!feof($handle)) {
$buffer .= fread($handle, $size);
// 可以对buffer进行其他处理
}
echo $buffer;
拿到文件的读取结果之后,立刻关闭文件句柄fclose($handle)
文件写入
fwrite($handle,$string,$length = null)
将字符串的指定字节长度(默认是全部)写入文件,要注意fopen创建的文件句柄是否有写的权限,该权限会不会导致已有内容被清空,文件的读写指针在默认在什么地方(比如r+会在开头写,替换原有字节长度(不是字符串度)的内容,比如一个汉字字符,替换掉原有的3个字符,或者3个字符替换原有的一个字符;而a+则是在最后追加,不产生覆盖行为)。注意在写入前面提到的换行符(其他特殊字符同样)的时候,不要使用‘\n’,单引号不发生转义,将原字符写入了文件,使用“\n”file_put_contents ($filename, $data, $flags = 0, $context = null)
,使用频率最高,可以写字符串、数组、流三种数据,如果文件存在,默认先清空该文件,设置$flag=FILE_APPEND
则是在最后追加,如果文件不存在,先创建该文件,前提是目标文件的所在父级目录要存在。
文件信息
fstat ($handle)
获取文件的全部信息这些信息也有对应的单独函数,比如:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29Array
(
[0] => 16777220
[1] => 8601984257
[2] => 33188
[3] => 1
[4] => 501
[5] => 20
[6] => 0
[7] => 3
[8] => 1533189738
[9] => 1533189529
[10] => 1533189529
[11] => 4194304
[12] => 8
[dev] => 16777220
[ino] => 8601984257
[mode] => 33188
[nlink] => 1
[uid] => 501
[gid] => 20
[rdev] => 0
[size] => 3 // 字节数
[atime] => 1533189738 // 上次访问时间
[mtime] => 1533189529 // 上次修改时间
[ctime] => 1533189529 // 创建时间
[blksize] => 4194304
[blocks] => 8
)filesize($file_name)、fileatime ($filename)、filemtime($filename)
…….
文件删除
unlink($filename)
,返回删除结果
修改文件名
rename($filepath, $newname)
修改文件或者文件夹的名称,参数1必须是真是存在的文件路径,参数2是新名称,也可以是改名之后的路径,但是必须要和原来的路径保持一致(父级),不能改到其他文件路径下。注意一点如果新文件名包含汉字,在window系统下(测试在mac下没这个问题,Linux估计也没问题),文件系统GBK、GB2312(好像是GB2312),而代码中的修改为UTF-8,为了防止文件名乱码,要把文件名把UTF-8编码转到这两种编码下iconv('utf-8','gbk', $new_file_name)
老谭PHP教学中总结,没有window电脑,此处没有具体尝试
获取文件mime
由于文件的后缀名是可该的,所以通过文件名的后缀部分来决定文件类型并不准确,可以使用如下几个函数
- mime_content_type($path)直接获取
- 通过finfo相关函数获取
1
2
3
4$info = finfo_open(FILEINFO_MIME);
$mime = finfo_file($info, 'view2.doc');
echo $mime; // image/png; charset=binary
fclose($info); 对于图片文件,还可以使用getimagesize($filename)函数获取,其结果如下
1
2
3
4
5
6
7
8
9Array
(
[0] => 703
[1] => 157
[2] => 3
[3] => width="703" height="157"
[bits] => 8
[mime] => image/png
)文件夹的操作
is_dir(file_path)
用于判断是否为文件夹mkdir($pathname, $mode = 0777, $recursive = false, $context = null)
用于创建文件夹,文件夹已存在则创建失败, recursive参数用于控制是否为多级文件夹。rmdir ($dirname, $context = null)
删除文件夹,只能删除最后一级的空的文件夹,若最后一级文件夹有文件,则删除失败一次删除文件夹下所有文件的扩展 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22function rrmove($filePath) {
if (is_dir($filePath)) {
$handle = opendir($filePath);
while (false !== ($file_name = readdir($handle))) {
if ($file_name != '.' && $file_name != '..') {
$file_full_path = $filePath . '/' . $file_name;
echo $file_full_path;
echo '<hr>';
if (is_dir($file_full_path)) {
rrmove($file_full_path);
} else {
unlink($file_full_path);
}
}
}
closedir($handle);
rmdir($filePath);
} else {
unlink($filePath);
}
}opendir($path)
用于打开一个文件夹,成功返回一个文件句柄readdir($handle)
从文件句柄中读取文件,多次调用,返回文件名,读取所有文件后,返回false