PHP 文件系统

1 文件与目录

1.1 解析目录路径

1) 返回路径中的文件名部分
string basename(string path, [, string suffix])
如果提供了可选参数suffix,当返回的文件名包含这个扩展名时将忽略该后缀。

echo "1) ".basename("/etc/sudoers.d", ".d").PHP_EOL;
echo "2) ".basename("/etc/passwd").PHP_EOL;
echo "3) ".basename("/etc/").PHP_EOL;
echo "4) ".basename(".").PHP_EOL;
echo "5) ".basename("/");

//输出
1) sudoers
2) passwd
3) etc
4) .
5)

2) 获取路径的目录
string dirname(string path)
返回路径的目录部分。

echo "1) " . dirname("/etc/passwd") . PHP_EOL; // 1) /etc
echo "2) " . dirname("/etc/") . PHP_EOL; // 2) / (or \ on Windows)
echo "3) " . dirname("."); // 3) .

3) 更多关于路径的信息
array pathinfo(string path [, options])
返回一个关联数组,其中包括路径的四部分信息:目录名、基本名、扩展名和文件名

$path_parts = pathinfo('/www/htdocs/inc/lib.inc.php');

echo $path_parts['dirname'], "\n";
echo $path_parts['basename'], "\n";
echo $path_parts['extension'], "\n";
echo $path_parts['filename'], "\n"; // since PHP 5.2.0

//输出
/www/htdocs/inc
lib.inc.php
php
lib.inc

4) 返回规范化的绝对路径名
string realpath(string path)
将path中的所有符号链接和相对路径引用转换为相应的硬链接和绝对路径。
realpath() 扩展所有的符号连接并且处理输入的 path 中的 ‘/./’, ‘/../’ 以及多余的 ‘/’ 并返回规范化后的绝对路径名。返回的路径中没有符号连接,’/./’ 或 ‘/../’ 成分
在 Windows 上,realpath() 会将 unix 风格的路径改成 Windows 风格的。

1.2 计算文件、目录和磁盘大小

1) 确定文件的大小
int filesize(string filename)返回指定文件的大小,以字节为单位。

2) 计算磁盘的可用空间
float disk_free_space(string directory)返回指定目录所在磁盘分区的可用空间,以字节为单位。

3) 计算磁盘的总容量
float disk_total_space(string directory)返回指定目录所在的磁盘分区的总容量,以字节为单位。

4) 获取目录大小,自定义函数

function directorySize($directory){
    $directorySize = 0;
    if($dh = @opendir($directory)){
        while($filename != “.” && $filename != “..”){
            if(is_file($directory.”/”.$filename))
                $directorySize += filesize($directory.”/”.$filename);

            if(is_dir($directory.”/”.$filename))
                $directorySize += directorySize($directory.”/”.$filename);
        }
    }
}

1.3 确定访问和修改时间

1) 取得文件的上次访问时间
int fileatime(string filename)返回文件最后的访问时间,采用UNIX时间戳格式。

2) 取得文件的 inode 修改时间
int filectiome(string filename)

3) 确定文件的最后修改时间
int filemtime(string filename) 返回文件的最后修改时间。

2 文件处理

2.1 打开和关闭文件

1) 打开文件或者 URL
resource fopen(string resource, string mode [, int use_include_path [, resource context]])
为移植性考虑,强烈建议在用 fopen() 打开文件时总是使用 ‘b’ 标记。

//fopen() 中 mode 的可能值列表

'r'    只读方式打开,将文件指针指向文件头。
'r+'    读写方式打开,将文件指针指向文件头。
'w'    写入方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。
'w+'    读写方式打开,将文件指针指向文件头并将文件大小截为零。如果文件不存在则尝试创建之。
'a'    写入方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。
'a+'    读写方式打开,将文件指针指向文件末尾。如果文件不存在则尝试创建之。
'x'    创建并以写入方式打开,将文件指针指向文件头。如果文件已存在,则 fopen() 调用失败并返回 FALSE,并生成一条 E_WARNING 级别的错误信息。如果文件不存在则尝试创建之。这和给 底层的 open(2) 系统调用指定 O_EXCL|O_CREAT 标记是等价的。
'x+'    创建并以读写方式打开,其他的行为和 'x' 一样。
'c'    Open the file for writing only. If the file does not exist, it is created. If it exists, it is neither truncated (as opposed to 'w'), nor the call to this function fails (as is the case with 'x'). The file pointer is positioned on the beginning of the file. This may be useful if it's desired to get an advisory lock (see flock()) before attempting to modify the file, as using 'w' could truncate the file before the lock was obtained (if truncation is desired, ftruncate() can be used after the lock is requested).
'c+'    Open the file for reading and writing; otherwise it has the same behavior as 'c'.

2) 关闭文件
boolean fclose(resource filehandle)
filehandle必须是使用fopen()或fsockopen()打开的已存在的文件指针。

2.2 读取文件

1) 把整个文件读入一个数组中
array file(string filename [int use_include_path [, resource context]]) 能够将文件读取到数组中,换行符附加在每个元素的末尾。
注意:file()很特殊,它不像其它读写函数,它不必建立文件句柄来读取文件内容。

2) 将整个文件读入一个字符串
string file_get_contents(string filename [int use_include_path [, resource context [, int offset [, int maxlen]]]]) 将文件中的内容读到字符串中。

file_get_contents 还可以用来发送post请求:

$opts = array('http' =>
  array(
    'method'  => 'POST',
    'header'  => "Content-Type: text/xml\r\n".
      "Authorization: Basic ".base64_encode("$https_user:$https_password")."\r\n",
    'content' => $body,
    'timeout' => 60
  )
);

$context  = stream_context_create($opts);
$url = 'https://'.$https_server;
$result = file_get_contents($url, false, $context, -1, 40000);

3) 从文件指针中读取一行
string fgets(resource handel [, int length])
从 handle 指向的文件中读取一行并返回长度最多为 length – 1 字节的字符串。碰到换行符(包括在返回值中)、EOF 或者已经读取了 length – 1 字节后停止(看先碰到那一种情况)。如果没有指定 length,则默认为 1K,或者说 1024 字节。

//逐行读取文件
$handle = @fopen("/tmp/inputfile.txt", "r");
if ($handle) {
    while (($buffer = fgets($handle, 4096)) !== false) {
        echo $buffer;
    }
    if (!feof($handle)) {
        echo "Error: unexpected fgets() fail\n";
    }
    fclose($handle);
}

4) 从文件指针中读取一行并过滤掉 HTML 标记
string fgetss(resource handle, int length [, string allowable_tags])
和fgets()函数类似,只是它从输入中清除所有HTML和PHP标签。如果要忽略某些标签,就把其放入allowable_tags中。参数 length 从 PHP 5 起开始可选。

5) 从文件指针中读取字符
stirng fgetc(resource handel)

$fp = fopen('somefile.txt', 'r');
if (!$fp) {
    echo 'Could not open file somefile.txt';
}
while (false !== ($char = fgetc($fp))) {
    echo "$char\n";
}

6) 读取文件
string fread(resource handle, int length)
fread不考虑换行符,当读取了length个字节或到达了EOF则停止,它有助于读取二进制文件。只要使用filesize()确定了应当读取的字符数,就能很方便使用这个函数读取整个文件。
如果只是想将一个文件的内容读入到一个字符串中,用 file_get_contents(),它的性能比下面的代码好得多。

$handle = fopen("http://www.example.com/", "rb");
$contents = '';
while (!feof($handle)) {
  $contents .= fread($handle, 8192);
}
fclose($handle);

7) 输出文件
int readfile(string filename [, int use_include_path]) 读取由filename指定的整个文件,立即输出到缓冲区并返回读取的字节数。

$file = 'monkey.gif';

if (file_exists($file)) {
    header('Content-Description: File Transfer');
    header('Content-Type: application/octet-stream');
    header('Content-Disposition: attachment; filename="'.basename($file).'"');
    header('Expires: 0');
    header('Cache-Control: must-revalidate');
    header('Pragma: public');
    header('Content-Length: ' . filesize($file));
    readfile($file);
    exit;
}
//会在客户端弹出一个可下载文件

8) 根据预定义的格式读取文件
mixed fscanf(resource handle, string format [, string var1]) 按照预定义的格式解析资源

$handle = fopen("users.txt", "r");
while ($userinfo = fscanf($handle, "%s\t%s\t%s\n")) {
    list ($name, $profession, $countrycode) = $userinfo;
    //... do something with the values
}
fclose($handle);

//users.txt
javier  argonaut        pe
hiroshi sculptor        jp
robert  slacker us
luigi   florist it

9) 从文件指针中读入一行并解析 CSV 字段
array fgetcsv(resource handle [, int length [, string delimiter [, string enclosure]]])
省略length或将其设为0都会导致任意的行长度。可以设置一个比最大行大的数值用来提升性能。

//file()和list()可以实现fgetcsv()函数的功能

$users = file(“/usr/data/s.csv”);
foreach($users as $user){
    list($name, $email, $phone) = explode(‘,’, $user);
    ….
}
//这种方式客观性更强一些。使用fgetcsv()时如果希望遇到换行符停止,那么不能指定长度,否则不可控。

10) 测试文件指针是否到了文件结束的位置
bool feof ( resource $handle )
如果文件指针到了 EOF 或者出错时则返回 TRUE,否则返回一个错误(包括 socket 超时),其它情况则返回 FALSE。

//如果传递的文件指针无效可能会陷入无限循环中,因为 feof() 不会返回 TRUE。
// 如果文件不可读取或者不存在,fopen 函数返回 FALSE
$file = @fopen("no_such_file", "r");

// 来自 fopen 的 FALSE 会发出一条警告信息并在这里陷入无限循环
while (!feof($file)) {
}

fclose($file);

11) 检查文件或目录是否存在
bool file_exists ( string $filename )

2.3 将字符串写入文件

int fwrite(resource handle ,string string [, int length]) 将字符串的内容输出到指定的资源中。

//If writing twice to the file pointer, then the data will be appended to the end of the file content:
$fp = fopen('data.txt', 'w');
fwrite($fp, '1');
fwrite($fp, '23');
fclose($fp);

// the content of 'data.txt' is now 123 and not 23!

2.4 移动文件指针

1) 将文件指针移到偏移量指定的位置
int fseek(resource handle, int offset [, int whence])

2) 获取当前指针的偏移量
int ftell(resource handle)

3) 将文件指针移回至文件开始处
int rewind(resource handle)

$handle = fopen('output.txt', 'r+');

fwrite($handle, 'Really long sentence.');
rewind($handle);
fwrite($handle, 'Foo');
rewind($handle);

echo fread($handle, filesize('output.txt'));

fclose($handle);

//输出
Foolly long sentence.

2.5 读取目录内容

1) 判断给定文件名是否是一个目录
bool is_dir ( string $filename )

2) 打开目录句柄
resource opendir(string path, [, resource context])

3) 关闭目录句柄
void closedir(resource directory_handle)

4) 解析目录内容
string readdir(resource dir_handle) 返回目录中下一个文件的文件名。文件名以在文件系统中的排序返回。

5) 将目录读入数组
array scandir(string directory [, int sorting_order [, resource context]])

3 执行shell命令

1) 新建目录
bool mkdir ( string $pathname [, int $mode = 0777 [, bool $recursive = false [, resource $context ]]] )
默认的 mode 是 0777,意味着最大可能的访问权。

2) 删除目录
int rmdir(string dirname)
尝试删除 dirname 所指定的目录。 该目录必须是空的,而且要有相应的权限。 失败时会产生一个 E_WARNING 级别的错误。

3) 重命名一个文件或目录
boolean rename(string oldname, string newname [, resource context])

rename ("/folder/file.ext", "/folder/newfile.ext");

4) 设定文件的访问和修改时间
int touch(string filename [, int time [, int atime]]) 文件不存在将创建空文件


参考文献

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

*