PHP文件系统处理

文件类型

  PHP是以UNIX的文件系统为模型的,因此在Window系统中我们只能获得“file”、“dir”、或者“unknown”三种文件类型。而在UNIX系统中,我们可以获得“block”、“char”、“dir”、“fifo”、“file”、“link”和“unknown”7种类型。

文件类型 描述
Block 块设备文件,如某个磁盘分区、软驱、光驱CD-ROM等
Char 字符设备是指在I/O传输过程中以字符为单位进行传输的设备,例如键盘,打印机等
Dir 目录类型,目录也是文件的一种
Fifo 命名管道,常用于将信息从一个进程传递到另一个进程
File 普通文件类型,如文本文件或可执行文件
Link 符号链接,是指向文件指针的指针,类似Window中的快捷方式
Unknown 位置类型

  在PHP中可以使用filetype()函数获取文件的类型,该函数接收一个文件名作为参数,如果文件不存在将返回FALSE。

/*
 * 获取Linux系统下文件类型
 */
echo filetype('/etc/passwd');
//输出file,/etc/passwd为普通文件

echo filetype('/etc/grub.conf');
//输出link,/etc/grub.conf为链接文件-》/boot/grub/grub.conf

echo filetype('/etc/');
//输出dir,/etc/为一个目录,即文件夹

echo filetype('/dev/sda1');
//输出block,/dev/sda1为块设备,它是一个分区

echo filetype('/dev/tty01');
//输出char,为字符设备,它是一个字符终端

  对于一个已知的文件,还可以使用is_file()函数判断给定的文件名是否为一个正常的文件。和它类似,使用is_dir()函数判断给定的文件名是否是一个目录,使用is_link()函数判断给定的文件名是否为一个符号链接。

文件属性

  在进行编程时,需要使用到文件的一些常用的属性,如文件的大小、文件的类型、文件的修改时间、文件的访问时间和文件的权限。

函数名 作用 参数 返回值
file_exists() 检查文件或目录是否存在 文件名 文件存在返回TRUE,不存在则返回FALSE
filesize() 获取文件大小 文件名 返回文件大小的自己数,出错返回FALSE
is_readable() 判断给定文件名是否可读 文件名 如果文件存在且可读则返回TRUE
is_writable() 判断给定文件名是否可写 文件名 如果文件存在且可读写则返回TRUE
is_executable() 判断给定文件名是否可执行 文件名 如果文件存在且可执行则返回TRUE
filectime() 获取文件的创建时间 文件名 返回UNIX时间戳格式
filemtime() 获取文件的修改时间 文件名 返回UNIX时间戳格式
fileatime() 获取文件的访问时间 文件名 返回UNIX时间戳格式
stat() 获取文件大部分属性值 文件名 返回关于给定文件有用的信息数组
header("Content-type:text/html;charset=utf-8");
date_default_timezone_set("Asia/Shanghai");
/*
 * 声明一个函数,通过传入一个文件名称获取文件的部分属性
 * @param string $filename 文件名称
 */
function getFilePro($filename){
    if(!file_exists($filename)){
        echo '目标文件不存在!!<br />';
        return;
    }
    if(is_file($filename)){
        echo $filename.'是一个文件<br />';
    }
    if(is_dir($filename)){
        echo $filename.'是一个目录<br />';
    }

    echo '文件的类型:'.getFileType($filename).'<br />';
    echo '文件的大小:'.getFileSize(filesize($filename)).'<br />';

    if(is_readable($filename)){
        echo '文件可读<br />';
    }
    if(is_writable($filename)){
        echo '文件可写<br />';
    }
    if(is_executable($filename)){
        echo '文件可执行.<br />';
    }

    echo '文件建立时间:'.date('Y-m-d H:i:s',filectime($filename)).'<br />';
    echo '文件最后修改时间:'.date('Y-m-d H:i:s',filemtime($filename)).'<br />';
    echo '文件最后访问时间:'.date('Y-m-d H:i:s',fileatime($filename)).'<br />';
}

getFilePro('1111.txt');
/*
 * 声明一个函数用来返回文件的类型
 * @param string $filename 文件名称
 */
function getFileType($filename){
    switch(filetype($filename)){
        case 'file':
            $type = "普通文件";
            break;
        case 'dir':
            $type = '目录文件';
            break;
        case 'block':
            $type = '块设备文件';
            break;
        case 'char':
            $type = '字符设备文件';
            break;
        case 'fifo':
            $type = '命名管道文件';
            break;
        case 'link':
            $type = '符号链接';
            break;
        case 'unknown':
            $type = '位置类型';
            break;
        default;
            $type = '没有检测到文件类型';
    }
    return $type;
}
/*
 * 自定义一个文件大小单位转换函数
 * @param int $bytes 文件大小的字节数
 * @return string 转换后带有单位的尺寸字符串
 */
function getFileSize($bytes){
    if($bytes >= pow(2,40)){
        $return = round($bytes/pow(1024,4),2);
        $suffix = 'TB';
    }else if($bytes >= pow(2,30)){
        $return = round($bytes/pow(1024,3),2);
        $suffix = 'GB';
    }else if($bytes >= pow(2,20)){
        $return = round($bytes/pow(1024,2),2);
        $suffix = 'MB';
    }else if($bytes >= pow(2,10)){
        $return = round($bytes/pow(1024,1),2);
        $suffix = 'KB';
    }else{
        $return = $bytes;
        $suffix = 'Byte';
    }
    return $return." ".$suffix;
}

目录的基本操作

  要描述一个文件的位置,可以使用绝对路径和相对路径。绝对路径是从根开始一级一级地进入各个子目录,最后指定该文件名或者目录名。而相对路径是从当前目录进入某个目录,最后指定该文件名或目录名。在系统的每个目录下都有两个特殊的目录“.”和“..”,分别指示当前目录和当前目录的父目录(上一级目录)。

$unixPath = '/var/www/html/index.php';
$winPath = 'C:\Appserv\www\index.php';
$winPath2 = 'C:/Appserv/www/index.php';

$fileName1 = 'file.txt';
$fileName2 = 'javascript/common.js';
$fileName3 = '../image/logo.gif';

  在UNIX系统中必须使用正斜线“/”作为路径分隔符,而在Windows系统中默认使用反斜线“”作为路径分割线,在程序中表示时还要将“”转义,但也接受正斜线“/”作为分割线的写法。为了程序可以有很好的移植性,建议都是用“/”作为文件的路径分隔符。另外,也可以使用PHP内部的常量DIRECTORY_SEPARATOR,其值为当前操作系统的默认文件路径分隔符。

$fileName2 = 'javascript'.DIRECTORY_SEPARATOR.'common.js';

  将目录路径中的各个属性分离开通常很有用,如末尾的扩展名、目录部分和基本名。可以通过PHP的系统函数basename()、dirname()和pathinfo()函数完成这些任务。

  1、basename()

  basename()返回路径中的文件名部分。该函数的原型如下所示:

  string basename(string path [,string suffix])

  该函数给出一个包含有指向一个文件全路径的字符串,本函数返回基本的文件名。第二个参数是可选参数,规定文件的扩展名。如果提供了则不会输出这个扩展名。

$path = '/var/www/html/page.php';
echo basename($path);
//显示带有文件扩展名的文件名,输出page.php

echo basename($path,'.php');
//显示不带文件扩展名的文件名,输出page

  2、dirname()

  该函数恰好与basename()相反,只需要一个参数,给出一个包含有指向一个文件的全路径的字符串,本函数返回去掉文件名后的目录名。

$path = '/var/www/html/page.php';
echo dirname($path);
//返回目录名/var/www/html

  3、pathinfo()

  函数pathinfo()返回一个关联数组,其中包括制定路径中的目录名、基本名和扩展名三个部分。分别通过数组键dirname、basename和extension来引用。

$path = '/var/www/html/index.php';
$path_parts = pathinfo($path);
echo $path_parts['dirname'];
//输出目录名/var/www/html
echo $path_parts['basename'];
//输出基本名index.php
echo $path_parts['extension'];
//输出扩展名php

遍历目录

  在进行PHP编程时,需要对服务器某个目录下面的文件进行浏览,通常称为遍历目录。取得一个目录下的文件和子目录,就需要用到opendir()函数、readdir()函数、closedir()函数和rewinddir()函数。

  • 函数opendir()用于打开指定目录,接受一个目录的路径作为参数,函数返回值为可供其他目录函数使用的目录句柄(资源类型)。如果目录不存在或者没有访问权限,则返回FALSE。
  • 函数readdir()用于读取指定的目录,接受已经用opendir()函数打开的可操作目录句柄作为参数,函数返回当前目录指针位置的一个文件名,并将目录指针向后移动一位。当指针位于目录的结尾时,因为没有文件存在则返回FALSE。
  • 函数closedir()关闭指定目录,接收已经用opendir()函数打开的可操作句柄作为参数。函数无返回值,运行后将关闭打开的目录。
  • 函数rewinddir()倒回目录句柄,接收已经用opendir()函数打开的可操作目录句柄作为参数。将目录指针重置目录到开始处,即倒回目录的开头。

 统计目录大小

  计算文件、磁盘分区和目录的大小在各种应用程序中都是常见任务。计算文件的大小可以通过前面介绍的filesize()函数完成,统计磁盘大小也可以使用disk_free_space()和disk_total_space()两个函数实现。但是PHP目前没有提供目录总大小的标准函数,因此我们需要自定义一个函数来完成任务。

/*
 * 自定义一个函数,统计传入的目录大小
 * @param string $directory 目录名称
 * @return double 目录的尺寸大小
 */
function dirSize($directory){
    $dir_size = 0;
    if($dir_handle = @opendir($directory)){
        while($filename = readdir($dir_handle)){
            if($filename != '.' && $filename != '..'){
                $subFile = $directory.DIRECTORY_SEPARATOR.$filename;
                if(is_dir($subFile)){
                    $dir_size += dirSize($subFile);
                }
                if(is_file($subFile)){
                    $dir_size += filesize($subFile);
                }
            }
        }
        closedir($dir_handle);
        return $dir_size;
    }
}

$dir_size = dirSize('D:/phpStudy/WWW/demo');
echo round($dir_size/pow(1024,1),2).'KB';

建立和删除目录

  在PHP中,使用mkdir()函数只需传入一个目录名即可很容易地建立一个新目录。但是删除目录所用到的函数rmdir(),只能删除一个空目录并且目录必须存在。如果是非空的目录就需要先进入到目录中,使用unlink()函数将这个目录中的文件都删除掉,再回来将这个空目录删除。如果目录中还存在子目录,而且子目录也非空,就要使用递归的方法了。

/*
 * 自定义函数递归删除整个目录
 * @param string $directory 目录名
 */
function delDir($directory){
    if(file_exists($directory)){
        if($dir_handle = @opendir($directory)){
            while($filename = readdir($dir_handle)){
                if($filename != '.' && $filename != '..'){
                    $subFile = $directory.DIRECTORY_SEPARATOR.$filename;
                    if(is_dir($subFile)){
                        delDir($subFile);
                    }
                    if(is_file($subFile)){
                        unlink($subFile);
                    }
                }
            }
        }
        closedir($dir_handle);
        rmdir($directory);
    }
}
delDir('D:phpStudyWWWdemofiledemo');

复制目录

  要复制一个文件可以通过PHP提供的copy()函数完成,创建目录可以使用mkdir()函数,定义函数时,首先对源目录进行遍历,如果遇到的是普通文件,直接使用copy()函数进行复制。如果遍历时遇到一个目录,则必须建立该目录,然后再对该目录下的文件进行复制操作,如果还有子目录,则使用递归重复操作,最终将整个目录复制完成。

/*
 * 自定义函数递归复制带有子目录的目录
 * @param string $dirSrc 源目录名字字符串
 * @param string $dirTo 目标目录名字字符串
 */
function copyDir($dirSrc,$dirTo){
    if(!file_exists($dirTo)){
        mkdir($dirTo);
    }
    if($dir_handle = @opendir($dirSrc)){
        while($filename = readdir($dir_handle)){
            if($filename != '.' && $filename != '..'){
                $subSrcFile = $dirSrc.DIRECTORY_SEPARATOR.$filename;
                $subToFile = $dirTo.DIRECTORY_SEPARATOR.$filename;
                if(is_dir($subSrcFile)){
                    copyDir($subSrcFile,$subToFile);
                }
                if(is_file($subSrcFile)){
                    copy($subSrcFile,$subToFile);
                }
            }
        }
        closedir($dir_handle);
    }
}
copyDir('./dirSrc','./dirTo');

文件的打开与关闭

  在处理文件内容之前,通常需要建立与文件资源的连接,即打开文件。同样,结束该资源的操作之后,应当关闭连接资源。所谓打开文件,实际上是建立文件的各种有关信息,并使文件指针指向该文件,就可以将发起输入或输出流的实体联系在一起,以便进行其他操作。关闭文件则断开指针与文件的联系,也就禁止再对文件进行操作。

  1、函数fopen()

  该函数用来打开一个文件,并在打开一个文件时,还需要指定如何使用它。也就是以哪种文件模式打开文件资源。

  resource fopen(string filename,string mode [,bool use_include_path [,resource zcontext]])

  第一个参数需要提供要被打开文件的URL。这个URL可以是脚本所在服务器中的绝对路径,也可以是相对路径,还可以是网络资源中的文件。

  第二个参数需要提供文件模式,文件模式可以告诉操作系统如何处理来自其他人或脚本的访问请求,以及一种用来检查你是否有权限访问这个特定文件的方法。当在打开文件时有三种选择:

  • 打开一个文件为了只读、只写或者是读和写。
  • 如果要写一个文件,可以覆盖所有已有的文件内容,或者需要将新数据追加到文件末尾。
  • 如果在一个区分二进制文件和纯文本文件的系统上写一个文件,还必须制定采用的方式。

  函数fopen()也支持以上三种方式的组合,只需要在第二个参数中提供一个字符串,指定将对文件进行的操作即可。

模式 描述
r 只读方式打开文件,从文件开头开始读
r+ 读写方式打开文件,从文件开头开始读写
w

只写方式打开文件,从文件开头开始写。如果文件已经存在,将文件指针指向文件头并将文件大小截为零,即删除所有文件已有内容,如果该文件不存在,函数将创建这个文件

w+

读写方式打开文件,从文件开头开始读写。如果文件已经存在,将文件指针指向文件头并将文件大小截为零,即删除所有文件已有内容。如果文件不存在,函数将创建这个文件

x

创建并以写入方式打开,将文件指针指向文件头。如果文件已存在,则fopen()调用失败并返回FALSE,并生成一条E_WARNING级别的错误信息。如果文件不存在则尝试创建。仅能用于本地文件

x+

创建并以读写方式打开,将文件指针指向文件头。如果文件已存在,则fopen()调用失败并返回FALSE,并生成一条E_WARNING级别的错误信息。如果文件不存在则尝试创建。仅能用于本地文件

a

写入方式打开,将文件指针指向文件末尾。如果该文件已有内容,将从该文件末尾开始追加。如果该文件不存在,函数将创建这个文件

a+

写入方式打开,将文件指针指向文件末尾。如果文件已有内容,将从文件末尾开始追加或者读。如果文件不存在,函数将创建这个文件

b

以二进制模式打开文件,用于与其他模式进行连接。如果文件系统能够区分二进制文件和文本文件,你可能会使用它。例如Windows系统中可以区分,而UNIX系统则不区分。这个模式是默认的模式

t 以文本模式打开文件,这个模式也只能是Windows系统下一个选项,不推荐使用

  如果open()函数成功地打开一个文件,该函数将返回一个指向这个文件的文件指针。对该文件进行操作所使用的读、写以及其他的文件操作函数,都要使用这个资源来访问该文件。如果打开文件失败,则返回FALSE。

$handle = fopen('/home/rasmus/file.txt','r');
//使用绝对路径打开file.txt文件,选择只读模式,并返回资源$handle

$handle = fopen("{$_SERVER['DOCUMENT_ROOT']}/data/info.txt",'r');
//访问文档根目录下的文件,也以只读模式打开

$handle = fopen('C:\data\file.gif','wb');
//在Windows平台上,转义文件路径中的每个反斜线,或者用斜线,以二进制和只写模式组合

$handle = fopen('../data/info.txt','r');
//使用相对路径打开info.txt文件,选择只读模式,并返回资源$handle

$handle = fopen("http://www.demo.com",'r');
//打开远程文件,使用http协议只能以只读的模式打开

$handle = fopen("ftp://user:password@example.com/somefile.txt",'w');
//使用ftp协议打开远程文件,如果ftp服务器可写,则可以以写模式打开

  2、函数fclose()

  资源类型属于PHP的基本类型,一旦完成资源的处理,一定要将其关闭,否则可能会出现一些预料不到的错误。函数fclose()就会撤销fopen()打开的资源类型,成功时返回TRUE,否则返回FALSE。参数必须是使用fopen()或fsockopen()函数打开已存在的文件指针。

 写入文件

  将程序中的数据保存到文件中比较容易,使用fwrite() 函数就可以将字符串内容写入到文件中。在文件中通过字符序列 表示换行符,表示文件中一行的结尾。当需要一次输入或输出一行时,请记住这一点。不同的操作系统具有不同的结束符号,基于UNIX的系统使用“ ”作为行结束符号,基于Windows的操作系统使用“ ”作为行结束符号,基于Mac的系统使用“ ”作为行结束字符。当要写入一个文本文件并想插入一个新行时,需要使用相应操作系统的行结束符号。

  int fwrite(resource handle,string string [,int length])

  第一个参数需要提供fopen()函数打开的文件资源,该函数将第二个参数提供的字符串内容输出到第一个参数指定的资源中。如果给出了第三个可选参数length,fwrite()将在写入了length个字符是停止。否则将一直写入,直到到达内容结尾才停止。如果写入的内容少于length个字节,该函数也会在写完全部内容后停止。函数fwrite()执行完成以后会返回写入的字符数,出现错误则返回FALSE。

$fileName = 'data.txt';
$handle = fopen($fileName,'w') or die('打开<b>'.$fileName.'</b>文件失败');
for($row = 0; $row < 10; $row++){
    fwrite($handle,$row.": www.demo.com
");
}
fclose($handle);

  该程序执行后,如果当前目录下存在data.txt文件,则清空该文件并写入10行数据。如果不存在data.txt文件,则会创建该文件并将10行数据写入。另外,写入文件还可以使用fput()函数,该函数是fwrite()函数的别名函数。如果需要快速写入文件,可以使用file_put_contents()函数。

$fileName = 'data.txt';
$data = "共10行数据
";
for($row = 0; $row < 10; $row++){
    $data .= $row.": www.demo11.com
";
}
file_put_contents($fileName,$data);

  该函数可以将数据直接写入到指定的文件中。如果同时调用多次时,并向同一文件中写入数据,则文件中只保存最后一次调用该函数写入的数据。因为在每次调用时都会重新打开文件并将文件原有的数据清空,所以不能像第一个程序一样连续多次写入多行数据。

读取文件内容

函数 描述
fread() 读取打开的文件
file_get_contents() 将文件读入字符串
fgets() 从打开的文件中返回一行
fgetc() 从打开的文件中返回字符
file() 把文件读入一个数组中
readfile() 读取一个文件,并输出到输出缓存

  在读取文件时,不仅要注意行结束符号“ ”,程序也需要一种标准的方式来识别何时到达文件的结尾,这个标准通常称为EOF(End Of File)字符。在PHP中,使用feof()函数。该函数接受一个打开的文件资源,判断一个文件指针是否位于文件的结束处,如果在文件结尾处,则返回TRUE。

  1、函数fread()

  该函数用来在打开的文件中读取指定长度的字符串。也可以安全用于二进制文件,在区分二进制文件和文本文件的系统上(如Windows)打开文件时,fopen()函数的mode参数要加上“b”。

  string fread(int handle,int length)

  该函数从文件指针资源handle中读取最多length个字节。该函数返回读取的内容字符串,如果失败则返回FALSE。

$fileName = 'data.txt';
$handle = fopen($fileName,'r') or die("文件打开失败");
$content = fread($handle,100);
fclose($handle);
echo $content;

  

$fileName = '1.jpg';
$handle = fopen($fileName,'rb');
$content = "";
while(!feof($handle)){
    $content .= fread($handle,1024);
}
fclose($handle);
echo $content;

  如果你只是想将一个文件的内容读入到一个字符串中,可以用file_get_contents()函数,它的性能比上面的代码好的多。file_get_contents()函数时用来将文件的内容读入到一个字符串中的首选方法。

echo file_get_contents('data.txt');
echo file_get_contents('1.jpg');

  2、函数fgets()、fgetc()

  该函数一次至多从打开的文件资源中读取一行内容。

  string fgets(int handle[ ,int length])

  第一个参数提供使用fopen()函数打开的资源。如果提供了第二个可选参数length,该函数返回length-1个字符。或者返回遇到换行或EOF之前读取的所有内容。如果忽略可选参数的length参数,默认为1024个字符。在大多数情况下,这意味着fgets() 函数将读取到1024个字符前遇到换行符号,因此每次成功调用都会返回下一行。如果读取失败则返回FALSE。

$handle = fopen('data.txt','r') or die('打开文件失败');
while(!feof($handle)){
    $buffer = fgets($handle,1024);
    echo $buffer.'----';
}
fclose($handle);

  函数fgetc()在打开的文件资源中只读取当前指针位置处的一个字符。如果遇到文件结束标志EOF,将返回FALSE值。

$handle = fopen('data.txt','r') or die('打开文件失败');
while(false !== ($char = fgetc($handle))){
    echo $char.'----';
}
fclose($handle);

  3、函数file()

  该函数非常有用,与file_get_contents()类似,不需要使用fopen()函数打开文件,不同的是file() 函数可以把整个文件读入到一个数组中。数组中的每个元素对应着文件中相应的行,个元素由换行符隔开,同时换行符仍附加在每个元素的末尾。

echo '<pre>';
print_r(file('data.txt'));

  4、函数readfile()

  该函数可以读取指定的整个文件,立即输出到输出缓存区,并返回读取的字节数。该函数也不需要使用fopen()函数打开文件。

echo readfile('data.txt');

  

原文地址:https://www.cnblogs.com/zhouguowei/p/9492422.html