PHP基礎教程十五之文件、目錄的操作

前言

我們在開發的時候,有時候需要涉及到圖片、文件的上傳下載等操作。比如註冊賬號的時候,有時候需要上傳頭像的圖片,這時候就需要用到文件的處理,而文件的樣式有很多種如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,訪問形式) 這個函數中訪問形式有很多,我們常用的只用三種:

    1. r,對文件進行讀的操作,文件指針指向頭部
    2. w,對文件進行寫的操作,如果文件存在,文件指針指向頭部,並把裏面的內容清空,如果文件不存在會創建文件。
    3. 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( 新的文件名)進行修改,當修改成功時返回true,失敗返回false。這個函數還可以移動文件的位置。

對目錄的操作

在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中對於文件的操作還是很重要的,對於文件的操作要靈活的應用不同的函數。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章