操作环境:windows平台 wamp 2.5; apache: 2.4.9; php:5.5.12; mysql:5.6.17;
一、 php文件系统概述
1.文件类型
php是以UNIX的文件系统为模型的,在windows系统里只能获得file、dir、unknown三种文件类型,
而在unix系统中,可以获得block、char、dir、fifo、file、link、unknown七种类型.
代码块
<?php
echo filetype('baidu.txt'); //输出file
echo '<hr/>';
echo filetype('test');//输出dir
echo '<hr/>';
//判断类型使用is_dir()这种函数
if(is_file('baidu.txt')){
echo 'file类型';
}
if(is_dir('test')){
echo 'dir类型';
}
?>
2.文件的属性
编程时,需要用到文件的常用属性,如文件的大小,文件的类型,文件的修改时间,文件的权限等等
常用属性
函数名 | 作用 | 返回值 |
---|---|---|
file_exists() | 检查文件或目录是否存在 | 存在返回true |
filesize() | 文件大小 | 文件大小字节数,出错返回false |
is_readable() | 判断文件是否可读 | 存在并且可读返回true |
is_writable() | 判断文件是否可写 | 存在并且可写返回true |
is_executable() | 判断文件是否可执行 | 存在并且可执行返回true |
filectime() | 创建时间 | 返回unix时间戳格式 |
filemtime() | 修改时间 | 返回unix时间戳格式 |
fileatime() | 访问时间 | 返回unix时间戳格式 |
stat() | 获取文件大部分属性值 | 数组 |
代码块
<?php
if(file_exists('down12.php')){
echo filesize('down12.php');//注意文件大小而不是文件夹
}
if(is_readable('baidu.txt')){
echo 2;
}
if(is_writable('baidu.txt')){
echo 3;
}
echo '<hr/>';
echo filectime('baidu.txt');
echo '<hr/>';
echo date('Y:m:d H:i:s',filectime('baidu.txt'));
var_dump(stat('baidu.txt'));
?>
<?php
/*
*文件大小转换函数
*
* */
function getFileSize($bytes){
if($bytes >= pow(1024, 4)){
$return = round($bytes/ pow(1024, 4));
$unit = 'TB';
}elseif ($bytes >= pow(1024, 3)) {
$return = round($bytes/ pow(1024, 3));
$unit = 'GB';
}elseif ($bytes >= pow(1024, 2)) {
$return = round($bytes/ pow(1024, 2));
$unit = 'MB';
}elseif ($bytes >= pow(1024, 1)) {
$return = round($bytes/ pow(1024, 1));
$unit = 'KB';
} else {
$return = $bytes;
$unit = 'byte';
}
return $return.$unit;
}
echo getFileSize(filesize('baidu.txt'));//输出14KB
var_dump(stat('baidu.txt'));
echo '<hr/>';
echo getFileSize(stat('baidu.txt')['size']);//输出14KB
?>
二、目录的基本操作
1.解析目录路径
描述一个文件的目录,可以使用绝对路径和相对路径。
系统的每个目录下都有两个特殊目录‘.’和’..’;分别指示当前目录和当前目录的父目录
代码块
// c:\wamp\www\index.php //window下;
// '/user/local/wamp' //linux下;
// 1.所有程序,用 "/"代表路径分隔符,window也兼容;
// 2.DIRECTORY_SEPARATOR,PATH_SEPARATOR,PHP_EOL跨平台使用;
// PATH_SEPARATOR目录分隔符在 windows下是";" , linux ":" ;
// DIRECTORY_SEPARATOR路径分隔符在windows下是 "\",linux上就是"/" ;
// echo 'a'.DIRECTORY_SEPARATOR.'file';
// echo 'a'.PATH_SEPARATOR.'file';
// 在unix世界换行就用/n来代替,但是windows就用/r/n,更有意思的是在mac中用/r,
//PHP里可以用PHP_EOL实现兼容
// 3. "."和 ".."
// 相对路径
// aaa/bbb/c.php
// ./aaa/bbb/c.php
//
// ../aaa/bbb
// ../../aaa/bbb
// 绝对路径
// c:/aaa/bbb
// /user/hello/
// http://www.lampbrother.net/php1.php
4.不同的根路径
// 一个是文档的根目录(浏览器使用的)
// <img src="/1.jpg" >
// 一个是操作系统的根(php操作的)
// mkdir('/newdir'); 如果是在windows平台D:\wamp\www里,则新目录创建在d:下
2.遍历目录
代码块
<?php
$dirn = 0 ;//目录数
$filen = 0 ;//文件数
function getDirNum($file){
global $dirn,$filen;
$dir = opendir($file);
while ($filename = readdir($dir)){
if($filename!='.' && $filename!='..'){
$filename = $file.DIRECTORY_SEPARATOR.$filename;
if(is_dir($filename)){
getDirNum($filename);
$dirn++;
}else{
$filen++;
}
}
}
closedir($dir);
}
getDirNum('image333');
echo "目录数为:{$dirn} <br>";
echo "文件数为:{$filen} <br>";
//获得文件和目录的数量封装函数
function getDirNum($file){
$arr=array(
'dirn'=>0,//目录数
'filen'=>0//文件数
);
$dir = opendir($file);
while ($filename = readdir($dir)){
if($filename!='.' && $filename!='..'){
$filename = $file.DIRECTORY_SEPARATOR.$filename;
echo $filename.'<br>';
if(is_dir($filename)){
$tmp=getDirNum($filename);//递归调用
$arr['dirn']=$tmp['dirn']+1;
$arr['filen']=$arr['filen'] + $tmp['filen'];
var_dump($tmp).'<br/>';
}else{
$arr['filen']=$arr['filen']+1;
var_dump($arr).'<br/>';
}
}
}
closedir($dir);
return $arr;
}
$arrVal = getDirNum('image333');
//var_dump($arrVal);
echo "目录数为:".$arrVal['dirn']." <br>";
echo "文件数为:".$arrVal['filen']." <br>";
?>
3.统计目录大小
代码块
<?php
//统计目录大小
function getDirNum($file){
$size = 0;
$dir = opendir($file);
while ($filename = readdir($dir)){
if($filename!='.' && $filename!='..'){
$filename = $file.DIRECTORY_SEPARATOR.$filename;
if(is_dir($filename)){
$size+=getDirNum($filename);
}else{
$size+=filesize($filename);
}
}
}
closedir($dir);
return $size;
}
echo tosize(getDirNum('image333')); //输出大小
//文件大小转换函数
function tosize($size){
$s = $size;
$du = "";
if($size>pow(2,40)){
$s = $size/pow(2,40);
$du = 'TB';
}elseif ($size> pow(2, 30)) {
$s = $size/pow(2,30);
$du = 'GB';
}elseif ($size> pow(2, 20)) {
$s = $size/pow(2,20);
$du = 'MB';
}elseif ($size> pow(2, 10)) {
$s = $size/pow(2,10);
$du = 'KB';
}else{
$s=$size;
$du='types';
}
return $s.$du;
}
?>
4.建立和删除目录
代码块
<?php
if(file_exists('hah3')){
echo '文件已存在';
}else{
mkdir('hah3');
}
$file = fopen('hah3/text.txt', 'w');
fwrite($file, 'this is a test');
fclose($file);
//递归的删除整个目录
function delDir($dirname){
if(file_exists($dirname)){
if(is_file($dirname)){
unlink($dirname);
}
$dir = opendir($dirname);
while($filename = readdir($dir)){
if($filename!='.'&&$filename !='..'){
$filename = $dirname.DIRECTORY_SEPARATOR.$filename;
if(is_dir($filename)){
delDir($filename);
}else{
unlink($filename);
}
}
}
closedir($dir);
rmdir($dirname); //删除空文件
}else{
echo '文件不存在';
}
}
deldir('hah3');//调用函数删除
?>
5.复制目录
代码块
<?php
function copyDir($dirSrc,$dirTo){
if(is_file($dirTo)){
die('目标不是目录不能创建');
}
if(!file_exists($dirTo)){
mkdir($dirTo);
}
$file = opendir($dirSrc);
while ($filename = readdir($file)){
if($filename!='.' && $filename!='..'){
$filenameSrc=$dirSrc.DIRECTORY_SEPARATOR.$filename;//源文件或目录
$filenameTo=$dirTo.DIRECTORY_SEPARATOR.$filename;//目标文件或目录
if(is_dir($filenameSrc)){
copyDir($filenameSrc, $filenameTo);
}
if(is_file($filenameSrc)){
copy($filenameSrc,$filenameTo);
}
}
}
closedir($file);
}
copyDir('image333','newdir02/image333');
?>
三、文件的基本操作
1.文件的打开与关闭
在函数fopen中的第二个参数可以使用的文件模式
模式字符 | 描述 |
---|---|
r | 只读方式打开文件,文件指针在开始 |
r++ | 读写方式打开文件,文件指针在开始 |
w | 只写方式打开文件,文件指针在开始。如果文件存在,把文件内容删除,如果文件不存在,则创建文件 |
w+ | 读写方式打开文件,文件指针在开始。如果文件存在,把文件内容删除,如果文件不存在,则创建文件 |
a | 写入方式打开,文件指针在末尾,如果文件已由内容,将从文件末尾追加(相当于数组的push),如果文件不存在,则创建文件 |
a+ | 写入方式打开,文件指针在末尾,如果文件已由内容,将从文件末尾追加或者读(相当于数组的push),如果文件不存在,则创建文件 |
代码
$handle = fopen('feng2.txt', 'r');//以只读方式打开文件
$handle2 = fopen('https://www.baidu.com/', 'r');//http协议只能以只读方式打开文件
2.写入文件
代码
$fileName = "feng222.txt";
$handle = fopen($fileName, 'w') or die('打开失败');
for($row = 0; $row<10; $row++){
fwrite($handle, $row.':::'.PHP_EOL);//写入文件
}
fclose($handle);
$fileName = "feng222.txt";
$data = "";
for($row = 0;$row<10;$row++){
$data .= $row."::".PHP_EOL;
}
file_put_contents($fileName, $data);//将一个字符串写入文件
3.读取文件内容
fread(),fgets()、fgetc(),file(),readfile(),file_get_contents();
$fileName = "feng222.txt";
$fp = fopen($fileName, 'r');
$content = fread($fp, 8);//从文件中读取前8个字节
fclose($fp);
echo $content;
$fileName = "feng222.txt";
$fp = fopen($fileName, 'r');
$content = fgetc($fp);//从文件中读取1个字节
fclose($fp);
echo $content;
$fileName = "feng222.txt";
$fp = fopen($fileName, 'r');
$content = fgets($fp);//从文件中读取1行
fclose($fp);
echo $content;
var_dump(file('feng222.txt'));//将内容读入数组并输出
readfile('feng222.txt');//直接将数据读出并输出到浏览器;
echo $str = file_get_contents('https://www.baidu.com/');
//将一个文件读入到字符串中,并输出;
4.访问远程文件
/*
*php可以通过http协议来访问服务器中的文件,只能以只读方式打开
*如果访问的是 FTP,并对提供的用户开启了“可写”权限,就可以使用只写或只读模式打开文件,不可以使用“可读可写”模式;
* */
$file = fopen("https://www.baidu.com/", 'r');
$pattern = "/<[^>]+>(.*)<\/[^>]+>/";
while (!feof($file)){
$line = fgets($file);
//找到标题,退出循环
if(preg_match("/<title>(.*)<\/title>/", $line,$out)){
$title = $out[1];
break;
}
}
fclose($file);
echo $title;
5.移动文件指针
代码
<?php
//$fp = fopen('feng222.txt', 'r');
//echo ftell($fp);
//echo fread($fp, 5);//读取文件的前5个字符,指针发生变化
//echo ftell($fp);
//fclose($fp);
//$fp = fopen('feng222.txt', 'r');
//echo ftell($fp);
//fseek($fp, 4);//文件指针移到4
//echo ftell($fp);
//rewind($fp);//重置文件指针,将文件指针移到开始位置
//echo ftell($fp);
//fclose($fp);
//注意,如果以a或a++模式打开,写入文件总是会附加到后面,而不顾指针的位置
$fp = fopen('feng222.txt', 'a');
echo ftell($fp);
fseek($fp, 4);//文件指针移到4
fwrite($fp, 'iiioooppp');
readfile('feng222.txt');//没有从4开始追加,而是附到后面
echo ftell($fp);
fclose($fp);
?>
6.文件的锁定机制
bool flock ( int handle, int operation [, int &wouldblock] );
flock() 操作的 handle 必须是一个已经打开的文件指针。operation 可以是以下值之一:
- 要取得共享锁定(读取数据),将 operation 设为 LOCK_SH
- 要取得独占锁定(写入数据),将 operation 设为 LOCK_EX
- 要释放锁定(无论共享或独占),将 operation 设为 LOCK_UN
- 如果你不希望 flock() 在锁定时堵塞,则应在上述锁定后 加上 LOCK_NB
代码
<?php
$file = fopen('feng2222.txt', 'w');//写的模式
flock($file, LOCK_EX+LOCK_NB);
fwrite($file, "Write something and");
flock($file, LOCK_UN+LOCK_NB);
fclose($file);
?>
7.文件的一些基本操作函数
文件的基本操作函数
函数 | 语法结构 | 描述 |
---|---|---|
copy() | copy(来源文件,目的文件) | 复制 |
unlink() | unlink(目标文件) | 删除 |
ftruncate() | ftruncate(目标文件资源,截取长度) | 将文件截断到指定的长度 |
rename() | rename(旧文件名,新文件名) | 重命名文件或目录 |
代码
if(copy('feng2222.txt', 'uploadfiles/feng2222.txt')){
echo '复制成功';
}else{
echo '复制失败';
}
$filename = 'uploadfiles/feng2222.txt';
if(file_exists($filename)){
if(unlink($filename)){
echo "文件删除成功";
}else{
echo "文件删除失败";
}
}else{
echo '文件不存在';
}
if(rename('uploadfiles/feng2222.txt', 'uploadfiles/feng3333.txt')){
echo '重命名成功';
}else{
echo '重命名失败';
}
$file = fopen('feng222.txt', 'r+') or die('文件打开失败');
if(ftruncate($file, 8)){
echo '截取成功';
}else{
echo '截取失败';
}
fclose($file);
四、文件的上传与下载
文件上传
php配置文件中与文件上传有关的选项(PHP上传设计的php.ini中的参数)
file_uploads 是否允许上传文件,默认ON
upload_tmp_dir 上传文件防止的临时目录,未指定则使用系统默认位置
upload_max_filesize 允许上传文件的大小的最大值,默认为2M
post_max_size 控制采用POST方法进行一次表单提交中PHP所能接受的最大数据量,如果希望用PHP文件上传,则此值要改为比upload_max_filesize要大
$_FILES数组内容
$_FILES[‘myfile’][‘name’]
浏览器端文件的原名称。$_FILES[‘myfile’][‘type’]
文件的 MIME 类型,如果浏览器提供此信息的话。一个例子是“image/gif”。不过此 MIME 类型在 PHP 端并不检查,因此不要想当然认为有这个值。$_FILES[‘myfile’][‘size’]
已上传文件的大小,单位为字节。$_FILES[‘myfile’][‘tmp_name’]
文件被上传后在服务端储存的临时文件名。$_FILES[‘myfile’][‘error’]
和该文件上传相关的错误代码。此项目是在 PHP 4.2.0 版本中增加的。
$_FILES[‘myfile’][‘error’] 错误代码
其值为 0,没有错误发生,文件上传成功。
其值为 1,上传的文件超过了 php.ini 中 upload_max_filesize 选项限制的值。
其值为 2,上传文件的大小超过了 HTML 表单中 MAX_FILE_SIZE 选项指定的值。
其值为 3,文件只有部分被上传。
其值为 4,没有文件被上传。
其值为 6,找不到临时文件夹。PHP 4.3.10 和 PHP 5.0.3 引进。
其值为 7,文件写入失败。PHP 5.1.0 引进。
代码
<?php
/*
文件的上传需要注意
1.post提交
2.添加enctype="multipart/form-data"
*/
error_reporting(E_ALL & ~E_NOTICE);
if($_POST['dosubmit']){
$size = 1000000; //设置充许大小为1M(1000000字节)以内的文件
var_dump($_POST);
var_dump($_FILES);
/*
array (size=2)
'MAX_FILE_SIZE' => string '1000000' (length=7)
'dosubmit' => string '提交' (length=6)
array (size=1)
'myfile' =>
array (size=5)
'name' => string '1.png' (length=5)
'type' => string 'image/png' (length=9)
'tmp_name' => string 'D:\wamp\tmp\php5B97.tmp' (length=23)
'error' => int 0
'size' => int 106500
*/
if(!file_exists('uploadfiles')){
mkdir('uploadfiles');
}
/* 判断文件是否可以成功上传到服务器,$_FILES['myfile']['error']值为0表示上传成功 ,其它值则出错*/
if($_FILES['myfile']['error'] > 0) {
echo '上传错误: ';
switch ($_FILES['myfile']['error']) {
case 1: die('上传文件大小超出了PHP配置文件中的约定值:upload_max_filesize');
case 2: die('上传文件大小超出了表单中的约定值:MAX_FILE_SIZE');
case 3: die('文件只被部分上载');
case 4: die('没有上传任何文件');
default: die('未知错误');
}
}
/* 判断上传的文件是否为充许尺寸范围内*/
if($_FILES['myfile']["size"] > $size){
die("超过了充许的<b>{$size}<b>字节大小!");
}
if(move_uploaded_file($_FILES['myfile']['tmp_name'], 'uploadfiles/'.$_FILES['myfile']['name'])){
echo '上传成功';
} else {
echo '上传失败';
}
}
?>
<form method="post" enctype="multipart/form-data" action="">
<h2>文件上传</h2>
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" /><br>
选择上传的文件:<input type="file" name="myfile" /><br>
<input type="submit" name="dosubmit" />
</form>
多个文件上传
<?php
error_reporting(E_ALL & ~E_NOTICE);
if($_POST['dosubmit']){
$size = 1000000; //设置充许大小为1M(1000000字节)以内的文件
var_dump($_POST);
var_dump($_FILES);
/*
array (size=2)
'MAX_FILE_SIZE' => string '1000000' (length=7)
'dosubmit' => string '提交' (length=6)
array (size=1)
'myfile' =>
array (size=5)
'name' => string '1.png' (length=5)
'type' => string 'image/png' (length=9)
'tmp_name' => string 'D:\wamp\tmp\php5B97.tmp' (length=23)
'error' => int 0
'size' => int 106500
*/
if(!file_exists('uploadfiles')){
mkdir('uploadfiles');
}
/* 判断文件是否可以成功上传到服务器,$_FILES['myfile']['error']值为0表示上传成功 ,其它值则出错*/
for($i = 0; $i<count($_FILES['myfile']['name']); $i++){
if($_FILES['myfile']['error'][$i] > 0) {
echo '上传错误: ';
switch ($_FILES['myfile']['error'][$i]) {
case 1: die('上传文件大小超出了PHP配置文件中的约定值:upload_max_filesize');
case 2: die('上传文件大小超出了表单中的约定值:MAX_FILE_SIZE');
case 3: die('文件只被部分上载');
case 4: die('没有上传任何文件');
default: die('未知错误');
}
}
/* 判断上传的文件是否为充许尺寸范围内*/
if($_FILES['myfile']["size"][$i] > $size){
die("{$_FILES['myfile']['name'][$i]}超过了充许的<b>{$size}<b>字节大小!");
}
if(move_uploaded_file($_FILES['myfile']['tmp_name'][$i], 'uploadfiles/'.$_FILES['myfile']['name'][$i])){
echo $_FILES['myfile']['name'][$i].'上传成功';
} else {
echo $_FILES['myfile']['name'][$i].'上传失败';
}
}
}
?>
<form method="post" enctype="multipart/form-data" action="">
<h2>文件上传</h2>
<input type="hidden" name="MAX_FILE_SIZE" value="1000000" /><br>
选择上传的文件:<input type="file" name="myfile[]" multiple /><br><!--multiple 多文件上传 -->
<input type="submit" name="dosubmit" />
</form>
文件下载
<!-- 下载页面 -->
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<title></title>
</head>
<body>
<a href="new.html.php" >下载</a>
</body>
</html>
//new.html.php页面
$filename= "new.html";
header("Content-Type:text/html"); //下载文件类型
header("Content-Disposition:attachment;filename={$filename}"); //下载文件描述
header('Content-Length:'.filesize($filename));
readfile($filename);//将'new.html'文件内容读取出来并直接输出,以便下载