前言
我們在開發的時候,有時候需要涉及到圖片、文件的上傳下載等操作。比如註冊賬號的時候,有時候需要上傳頭像的圖片,這時候就需要用到文件的處理,而文件的樣式有很多種如txt,word,excel等。
文件的傳輸方式
在PHP語言甚至於其他語言中操作文件的形式,實質上是操作流的。PHP中共有兩種流(字節流,二進制流)按照輸出的方式不同還分成輸入流和輸出流。
文件的流都是以內存參照的, 如果數據是從內存保存磁盤的文件中,我們稱爲輸出流,反過來,如果是從文件想內存流動,我們稱爲輸入流。
文件的操作方式
在PHP中文件的操作方式分爲兩種
- 本地操作
- 遠程操作
本地操作是在自己的電腦上對文件進行增刪改查等操作。
遠程操作是遠程訪問服務器,對服務器上的文件進行增刪改查等操作。
從幫助文檔中可以看到關於操作文件的函數:
這裏只是列出函數裏面的一些,更多的函數可以查看幫助文檔。可以看到在幫助文檔一共有81個函數,但是我們不用全部掌握,常用的就那幾個。
對文件的操作
讀取文件的相關信息
我們在操作文件時,有時候需要知道文件的相關信息,比如文件的大小,文件的類型,文件的創建時間,修改時間,訪問時間等等信息,這裏就會使用到讀取文件相關信息的技術,在PHP中分爲兩種形式進行文件信息的獲取。
讀取文件相關信息的第一種方式
<?php
//寫一個變量記錄文件的路徑
$file_path = "D:/config.txt";
if(file_exists($file_path)){
//文件存在
if($fp = fopen($file_path,'r')){
//$type是一個存放文件信息的數組
$type = fstat($fp);
echo '<br>文件的字節是:' . $type['size'];
echo '<br>文件創建時間是:' . date('Y-m-d H:i:s',$type['ctime']);
echo '<br>文件訪問時間是:' . date('Y-m-d H:i:s',$type['atime']);
echo '<br>文件修改時間是:' .date('Y-m-d H:i:s',$type['mtime']);
//關閉資源
fclose($fp);
}else{
echo '文件打開失敗';
}
}else{
echo '文件不存在';
}
......結果.......
文件的字節是:22
文件創建時間是:2016-10-12 20:34:56
文件訪問時間是:2016-10-12 20:34:56
文件修改時間是:2016-10-12 20:35:08
1. 我們先定義一個路徑是我們訪問的文件,這個路徑可以是相對路徑,也可以是絕對路徑。
2. 通過file_exists($path)函數判斷文件是否存在,存在返回true,不存在返回false.
3. 通過fopen($path,訪問形式),該函數打開一個文件,返回一個文件指針,指向第一行。第一個參數是文件的路徑,第二個參數是文件的訪問形式,“r”表示對文件進行讀。
4. fstat(文件指針)通過已打開的文件指針取得文件信息,返回一個數組,裏面有一些關聯數組是我們想要的值。
5. 使用完資源,記得關閉,不然有時候會出現出人意料的錯誤。
讀取文件信息的第二種方式
<?php
$file_path = 'D:/config.txt';
echo '<br>文件的類型是:' . filetype($file_path);
echo '<br>文件的大小是:' . filesize($file_path);
echo '<br>文件的創建時間是:' . date('Y-m-d H:i:s',filectime($file_path));
echo '<br>文件的訪問時間是:' .date('Y-m-d H:i:s',fileatime($file_path));
echo '<br>文件的修改時間是:' . date('Y-m-d H:i:s',filemtime($file_path));
.....結果.....
文件的類型是:file
文件的大小是:22
文件的創建時間是:2016-10-12 20:34:56
文件的訪問時間是:2016-10-12 20:34:56
文件的修改時間是:2016-10-12 20:35:08
這種方式比較簡單,通過函數來直接獲取文件的相關信息,不過應該在每個函數底層都打開了文件進行操作。
讀取文件的內容
我們操作文件往往需要讀取文件裏面的內容,PHP提供了三種方式來讀取文件。
讀取文件的第一種方式
<?php
header("Content-type:text/html;charset = utf-8");
$file_path = 'D:/config.txt';
if(file_exists($file_path)){
if($fp = fopen($file_path,'r')){
//獲取文件的大小
$file_size = fstat($fp)['size'];
$content = fread($fp, $file_size);
//對文件中中文進行編碼
$content = iconv('gbk', 'utf-8', $content);
//對換行符進行替換。
$content = str_replace("\r\n", "<br>", $content);
echo $content;
fclose($fp);
}else{
echo '文件打開失敗';
}
}else{
echo '文件不存在';
}
......結果.......
這是一些配置文件信息。
user = abc;
password = 122;
- 定義文件的全路徑
- file_exists($path)判斷文件是否存在
fopen($path,訪問形式) 這個函數中訪問形式有很多,我們常用的只用三種:
- r,對文件進行讀的操作,文件指針指向頭部
- w,對文件進行寫的操作,如果文件存在,文件指針指向頭部,並把裏面的內容清空,如果文件不存在會創建文件。
- a,對文件進行寫的操作,如果文件存在,文件指針指向尾部,不會把裏面的內容清空,如果文件不存在會創建文件。
fread(文件指針,大小)這個函數就是對文件進行度的操作,通過獲取文件的大小,把一個文件整體的寫入到$content中。
- iconv(輸入的字符集,輸出的字符集,字符串) 這個函數是把文件裏面的函數進行編碼,在文件中存儲方式gbk,在頁面中存儲方式是utf-8,
- str_replace(要替換的字符,替環字符,字符串)這個函數是把文件中的換行符進行轉換,在windows下文件的換行符是“\r\n”,文件的內容顯示在網頁上,網頁的換行符是”<\br>”,注意轉義字符必須用雙引號引起來。
- 關閉文件指針資源
讀取文件的第二種方式
在第一種方式中,讀取文件是一次性的讀取全部,當文件很大時,這種方式是不合理的,可以使用第二種方式,使用循環讀取,先讀取一部分,合併,在讀取一部分,合併。
<?php
$file_path = 'D:/config.txt';
if(file_exists($file_path)){
if($fp = fopen($file_path,'r')){
//文件太大,分字節度
$size = 1024;//每次讀取1024個字節
$tmp_content = '';//存放一次讀取的內容
$content = '';//存放總的內容。
while(!feof($fp)){
$tmp_content = fread($fp,$size);
$content .= $tmp_content;
}
$content = iconv('gbk', 'utf-8', $content);
$content = str_replace("\r\n", "<br>", $content);
echo $content;
fclose($fp);
}else{
echo '文件打開失敗';
}
}else{
echo '文件不存在';
}
......結果.......
這是一些配置文件信息。
user = abc;
password = 122;
- 從上面的代碼中可以看出來,讀取文件的內容是分塊讀取的,讀取一次,拼接到總的內容上。
- feof(文件指針) 測試文件指針是否到了文件結束的位置,當文件指針指向最後則不用循環。
- 關閉文件指針資源
讀取文件的第三種方式
<?php
$file_path = 'D:/config.txt';
$content = file_get_contents($file_path);
$content = iconv('gbk','utf-8',$content);
$content = str_replace("\r\n","<br>",$content);
echo $content;
......結果.......
這是一些配置文件信息。
user = abc;
password = 122;
第三種方式是最簡單的一種方式,通過file_get_contents()方法進行整體的讀取。
創建文件和寫文件
創建文件和寫文件第一種方式
<?php
//定義文件的路徑
$file_path = 'D:/test.txt';
if(!file_exists($file_path)){
//文件不存在
//fopen()函數使用w這種訪問形式,
if($fp = fopen($file_path, 'w')){
$str = '';
for($i = 0; $i < 10; $i++){
$str .= "hello,php\r\n";
}
//向文件中寫數據
fwrite($fp, $str);
fclose($fp);
}
}
- 當文件不存在的使用使用fopen()打開文件是自動創建文件的,這裏使用的文件訪問形式是w,文件指針指向頭部,清空文件裏面的內容。
- 通過fread()函數想文件中寫文件。
- 當文件存在的時候我們可以使用’a’這種訪問形式進行對文件內容的追加寫入。
創建文件和寫文件第二種方式
<?php
//定義文件的路徑
$file_path = 'D:/test.txt';
if(!file_exists($file_path)){
$str = '';
for($i = 0; $i < 10; $i++){
$str .= "hello,php\r\n";
}
file_put_contents($file_path, $str);
}
- 使用file_put_contents()函數進行文件的寫入,這個函數也是當文件不存在的時候,創建文件。
- 如果我們通過file_put_contents函數來追加新的內容到文件中,應該在使用file_put_contents函數時,帶上第三個參數 FILE_APPEND 即可。
刪除文件
<?php
$file_path = 'D:/test.txt';
if(file_exists($file_path)){
if(unlink($file_path)){
echo '文件刪除成功';
}else{
echo '文件刪除失敗';
}
}
- 通過unlink(文件路徑)函數刪除文件。
修改文件的名字
<?php
$file_path = 'D:/test.txt';
$file_newPath = 'D:/newtest.txt';
if(file_exists($file_path)){
if(rename($file_path,$file_newPath)){
echo '文件名修改成功';
}else{
echo '文件名修改失敗';
}
}
- 修改文件的名字可以通過rename(
對目錄的操作
在php文件編程中,目錄也是一種文件,是一種比較特殊的文件,因此對目錄的操作有固定的操作方法,主要的方法有三個 is_dir,rmdir,mkdir
- is_dir 判斷是否是一個目錄
- rmdir 刪除一個目錄,當目錄下面有文件或目錄的時候不能刪除。
mkdir 創建一個目錄
<?php $dir_path = 'D:/test'; //判斷目錄是否存在 if(is_dir($dir_path)){ echo '目錄存在'; }else{ //目錄不存在,創建目錄 if(mkdir($dir_path)){ echo '目錄創建成功'; }else{ echo '目錄創建失敗'; } }
- 上面先判斷目錄是否存在,不存在使用mkdir()函數進行目錄的創建。
上面的代碼只能創建一級目錄,當路徑名字換成$dir_path = ‘D:/test/a/b/c/d’時,在test目錄下還有目錄,這時候用上面的方法就會報錯,不能夠創建多級目錄。這時候也可以使用mkdir()函數進行創建,但是在函數中多了兩個參數,這兩個參數對於windows系統下開發是沒有意義的。
<?php
$dir_path = 'D:/test/a/b/c/d';
//判斷目錄是否存在
if(is_dir($dir_path)){
echo '目錄存在';
}else{
//目錄不存在,創建目錄
if(mkdir($dir_path,0777,true)){
echo '目錄創建成功';
}else{
echo '目錄創建失敗';
}
}
- 可以看到在創建目錄的函數中添加了兩個參數,就能創建多級目錄。0777是在linux下的最大訪問權限,而true是表示創建多級目錄。
刪除目錄
<?php
$dir_path = 'D:/test';
if(is_dir($dir_path)){
//目錄存在
if(rmdir($dir_path)){
echo '目錄刪除成功';
}else{
echo '目錄刪除失敗';
}
}
- 通過rmdir(目錄路徑)刪除目錄。
- 刪除目錄時,下面沒有目錄或者文件的存在。
- rmdir()函數只能刪除一個目錄,不能刪除多個目錄,刪除多個目錄,可以使用遞歸刪除。
<?php
//在這裏test目錄下的全目錄是:D:/test/a/b/c/d
$dir_path = 'D:/test';
delDir($dir_path);
function delDir($dir_path){
//打開當前的目錄
$dir = opendir($dir_path);
//通過readdir函數獲取目錄下的所有目錄
while(false !== ($fileName = readdir($dir))){
//對當前的目錄進行拼接
if($fileName != '.' && $fileName != '..'){
$dir_name = $dir_path . '/' . $fileName;
if(is_dir($dir_name)){
//是一個目錄,通過遞歸在此判斷。
delDir($dir_name);
//遞歸完成,當前目錄下爲空,刪除目錄。
}else if(is_file($dir_name)){
//是文件刪除文件。
unlink($dir_name);
}
}
}
closedir($dir);
rmdir($dir_path);
}
把文件刪除的操作封裝到函數中,如果目錄下沒有文件則while循環不會進入循環,而是直接刪除目錄。當有目錄或文件時,可以在循環中遞歸的執行函數,知道遇到是文件或目錄爲空(基準條件)。
文件的拷貝
<?php
//當前需要複製的文件路徑。
$file_path = 'D:/Desert.jpg';
//需要複製到哪的路徑
$path = "E:/desert.jpg";
if(file_exists($file_path)){
if(copy($file_path,$path)){
echo '複製成功';
}else{
echo '複製失敗';
}
}else{
echo '文件不存在';
}
- 定義的文件的全路徑
- 定義目標的路徑。
- 利用copy函數直接進行復制拷貝,第一個參數是文件的路徑,第二個參數是目標的路徑。
遍歷目錄
<?php
$dir_path = 'D:/test';
isDir($dir_path);
function isDir($dir_path){
if(is_dir($dir_path)){
//存在文件
$dir = opendir($dir_path);
//打開目錄
while(($fileName = readdir($dir)) !== false){
if($fileName != '.' && $fileName != '..'){
if(is_dir($dir_path . '/' . $fileName)){
echo '<br>目錄名是:' . $fileName;
isDir($dir_path . '/' . $fileName);
}else if(is_file($dir_path . '/' . $fileName)){
echo '<br>文件名是:' . $fileName;
}
}
}
//關閉資源
closedir($dir);
}
}
......結果.......
目錄名是:a
文件名是:a.txt
目錄名是:b
目錄名是:c
目錄名是:d
文件名是:n.doc
文件名是:c.txt
* 通過遞歸進行循環的判斷一個目錄下面的所有目錄和文件,進行輸出。
* 在每個目錄下都隱藏着兩個無用的目錄,所以通過if判斷把這兩個無用的目錄過濾掉。
統計目錄的大小。
<?php
$dir_path = 'D:/test';
echo getSize($dir_path);
function getSize($dir_path){
//定義字節。
$size = 0;
//判斷是否目錄
if(is_dir($dir_path)){
//打開目錄
$dir = opendir($dir_path);
//判斷每個目錄是否存在。
while(false !== ($fileName = readdir($dir))){
//過濾無用的兩個目錄。
if($fileName != '.' && $fileName != '..'){
if(is_dir($dir_path . '/' . $fileName)){
//通過遞歸進行循環的獲取字節大小。
$size += getSize($dir_path . '/' . $fileName);
}else if(is_file($dir_path . '/' . $fileName)){
$size +=filesize($dir_path . '/' . $fileName);
}
}
}
}
//關閉資源。
fclose($dir);
return $size;
}
.......結果.......
47
- 獲取目錄的字節通過遞歸完成。定義$size記錄每個文件的大小,返回。
總結
PHP中對於文件的操作還是很重要的,對於文件的操作要靈活的應用不同的函數。