电竞比分网-中国电竞赛事及体育赛事平台

分享

PHP中的文件系統(tǒng)函數(shù)(二)

 硬核項目經理 2021-05-31

PHP中的文件系統(tǒng)函數(shù)(二)

這次我們來學習的是一些不是太常用,但卻也非常有用的一些函數(shù)。它們中有些大家可能見過或者使用過,有一些可能就真的沒什么印象了。它們都是 PHP 中文件系統(tǒng)相關操作函數(shù)的一部分。存在即合理,或許只是我們的業(yè)務開發(fā)中還沒有接觸到而已。不管別的,先混個臉熟,在真正需要它們的時候你能馬上想起來 PHP 就自帶一個這樣的函數(shù)就可以了。

目錄判斷、創(chuàng)建、刪除、路徑緩存信息

var_dump(is_dir("./")); // bool(true)
var_dump(disk_free_space("./")); // float(7727517696)
var_dump(disk_total_space("./")); // float(250790436864)

is_dir() 函數(shù)估計大家會比較常用,就是用來判斷給定的路徑是否存在或者是否正常。一般在手動創(chuàng)建目錄之前都會使用這個函數(shù)來判斷一下目錄是否已經創(chuàng)建過了,常見于上傳相關的業(yè)務場景開發(fā)中。disk_free_space() 和 disk_total_space() 則是獲取指定目錄的剩余磁盤空間和總的磁盤空間數(shù)據(jù)的函數(shù)。因為我的電腦是 Mac 系統(tǒng),所以總的磁盤空間就是 250G 的,可用的空間為 7G ,看來馬上就要準備清理一下電腦了。

var_dump(mkdir("./a")); // bool(true)
var_dump(rmdir("./a"));  // bool(true)

mkdir() 函數(shù)用于創(chuàng)建一個目錄,它除了給定的路徑參數(shù)外,還有一個可選參數(shù)可以設置目錄的文件權限,也是傳遞 0777 之類的值就可以了,這個函數(shù)相信大家不會很陌生,大部分的文件上傳分目錄的能力正是使用 is_dir() 來配合 mkdir() 進行目錄創(chuàng)建的。rmdir() 是用于刪除目錄的,這個函數(shù)有兩個前提,一是要刪除的目錄必須是空的,二是要有刪除這個目錄的權限,如果任一條件不滿足的話,就會報出一個 E_WARNING 級別的錯誤。

realpath('./');
var_dump(realpath_cache_get());
// array(8) {
//     ["/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202010/source"]=>
//     array(4) {
//       ["key"]=>
//       float(1.4990943845035E+19)
//       ["is_dir"]=>
//       bool(true)
//       ["realpath"]=>
//       string(61) "/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202010/source"
//       ["expires"]=>
//       int(1603327834)
//     }
//     ["/Users/zhangyue/MyDoc/博客文章"]=>
//     array(4) {
//       ["key"]=>
//       int(8597410586338680)
//       ["is_dir"]=>
//       bool(true)
//       ["realpath"]=>
//       string(34) "/Users/zhangyue/MyDoc/博客文章"
//       ["expires"]=>
//       int(1603327834)
//     }
//     ["/Users"]=>
// ……
// ……

var_dump(realpath_cache_size()); // int(673)

realpath_cache_get() 函數(shù)用于獲取真實目錄緩存的詳情,我們需要先使用 realpath() 獲得一個目錄路徑,然后就可以看到 realpath_cache_get() 里面的內容??梢钥闯鏊祷氐臄?shù)組中,是這條路徑從第一個目錄到這個目錄中的所有目錄信息,包括每一級目錄的 realpath 、 is_dir 等屬性信息。realpath_cache_size() 獲取的是真實路徑緩沖區(qū)的大小,也就是真實路徑緩存區(qū)大小在內存中的使用量。

軟連接信息

上篇文章中我們已經學過了如何創(chuàng)建連接文件,這次我們再來看看兩個小的關于連接信息的函數(shù)。

var_dump(readlink('ltest2.txt')); // "test.txt"
var_dump(is_link('ltest2.txt')); // bool(true)

readlink() 函數(shù)用于獲得軟連接所連接到的真實文件的名稱。在上篇文章中,我們創(chuàng)建的 ltest2.txt 文件正是 test.txt 文件的軟連接。而 is_link() 函數(shù)則用于判斷給定的文件是否是一個連接文件。

拷貝、移動、改名、刪除文件操作

var_dump(copy('test.txt''cp_test.txt')); // bool(true)

var_dump(is_file("cp_test.txt")); // bool(true)

var_dump(move_uploaded_file('test.txt''mv_upload_test.txt')); // bool(false)
var_dump(is_file("mv_upload_test.txt")); // bool(false)
var_dump(is_uploaded_file("mv_upload_test.txt")); // bool(false)

var_dump(copy('test.txt''re_test.txt')); // bool(true)
var_dump(rename('re_test.txt''new_re_test.txt')); // bool(true)

var_dump(copy('test.txt''del_test.txt')); // bool(true)
var_dump(unlink("del_test.txt")); // bool(true)

對于文件來說,copy() 是非常常用的一個函數(shù)。不管是寫代碼還是日常辦公,復制粘貼這樣的拷貝操作都是我們工作中的重心所在。PHP 提供的 copy() 函數(shù)就是專門用于文件拷貝的,不過需要注意的是,一定要有文件和拷貝目標目錄的讀寫權限哦。

move_uploaded_file() 文件相信大家也是非常熟悉的,在上傳文件的操作中也是經常會用到的一個功能。不過需要注意的是,從文件名就可以看出,move_uploaded_file() 的作用是移動已上傳文件,也就是 $_FILES 里面 tmp 中的文件,它是不能當做 copy() 函數(shù)來使用的。從演示代碼中就可以看出,對于普通文件來說,它是無法拷貝移動的。is_uploaded_file() 函數(shù)就是用于判斷要操作的文件是不是一個 PHP 已上傳文件。

通過上面這兩個函數(shù),相信不少人都會想到文件上傳中他們的使用,這里就給出一個簡單的偽代碼。

if(!move_uploaded_file('xxxx''xxxx')){
    if(copy('xxxx''xxxx')){
        // 上傳成功
    }else{
        // 上傳失敗
    }
}

很多教程里都會有這樣的寫法,甚至一些框架中也會有這樣的寫法。其實就是先使用 move_uploaded_file() 去移動上傳文件,如果失敗了,再使用 copy() 函數(shù)拷貝一次。如果還是失敗了,就認為整個上傳操作失敗了。

rename() 函數(shù)用于給文件改名,其實它就是類似于 Linux 系統(tǒng)中的 mv 命令。

is_file() 函數(shù)用于判斷給定的文件是否是一個正常的文件。在操作系統(tǒng)中,特別是 Linux 系統(tǒng)中,一切皆文件,所以這個函數(shù)真正最常用的場景是判斷給定的路徑到底是目錄還是一個文件,很多時候我們會用它來判斷上傳成功后的文件是否正常,或者判斷一個給定的路徑到底是一個目錄還是一個文件。

最后就是 unlink() 函數(shù)。在 PHP 中,沒有 delete 或者 rm 這樣的函數(shù),unlink() 就是用于刪除文件的。不過它的名字起得卻像是要解除符號連接文件的連接一樣,不管是連接文件還是普通文件,都是通過這個 unlink() 函數(shù)來進行刪除的。

文件一次性讀取

關于文件一次性讀取到內容和流式按字節(jié)或行來讀取的內容我們之前已經有一篇文章詳細的學習講解過,大家可以在公眾號中回復 【PHP大文件讀取操作】 查看文章。所以這里我們就簡單的貼出代碼演示一下。

var_dump(file_exists('test.txt')); // bool(true)
var_dump(readfile('test.txt')); // asdfasdfint(8)
var_dump(file('test.txt'));
// array(1) {
//     [0]=>
//     string(8) "asdfasdf"
//   }

$c = file_get_contents('test.txt');
var_dump($c); // string(8) "asdfasdf"

var_dump(file_put_contents('fpc_test.txt', $c)); // int(8)

file_exists() 函數(shù)是專業(yè)的用于判斷文件是否存在的函數(shù),上面的 is_file() 會更多地用于上傳之后的操作。而 file_exists() 則是在日常的代碼編寫中非常常用的函數(shù)。readfile() 直接讀取文件內容到內容中,file_get_contents() 也是這樣的功能,只不過 file_get_contents() 返回的是以字符串為格式的文件內容。注意看我們 var_dump() 的結果,file_get_contents() 明顯的標了是 string(8) 這樣的類型,而 readfile() 是直接輸出內容,不走緩沖區(qū)的,也就是說它是類似于 phpinfo() 這樣的函數(shù)。需要使用 ob_start() 之類的函數(shù)才能將 readfile() 函數(shù)讀取的內容放到一個變量中,我們之前的文章也專門講過緩沖區(qū)的概念,公眾號回復【PHP中的輸出緩沖控制】 。它的返回值是文件的字節(jié)數(shù),也就是后面的 int(8) 。

file() 函數(shù)是將文件的內容保存到一個數(shù)組中,它會默認以行進行分隔,也就是每一行分為數(shù)組中的一個元素。

file_put_contents() 是將給定的內容寫入到一個文件中,和 file_get_contents() 配合也可以實現(xiàn)一個拷貝的操作。

文件屬性

var_dump(fileatime('test.txt')); // int(1603243708)
var_dump(filectime('test.txt')); // int(1603242166)
var_dump(filemtime('test.txt')); // int(1603242166)

var_dump(fileinode('test.txt')); // int(8707958352)
var_dump(filesize('test.txt')); // int(8)
var_dump(filetype('test.txt')); // string(4) "file"

var_dump(is_executable('test.txt')); // bool(true)
var_dump(is_writable('test.txt')); // bool(true)
var_dump(is_readable('test.txt')); // bool(true)

很明顯,fileatime() 、filectime() 、filemtime() 對應的就是文件的上次訪問時間、inode修改時間以及修改時間,和 Linux 系統(tǒng)中的文件相關的那三個時間概念一致。fileinode() 用于獲得文件的 inode 信息。filesize() 就是文件的大小,filetype() 是文件的類型信息。

is_executable() 用于判斷文件是否可以執(zhí)行,is_writable() 、is_readable() 判斷文件是否可以寫和讀。這三個函數(shù)對應的就是文件的權限相關的判斷。

創(chuàng)建不重名文件及臨時文件

var_dump(tempnam('./''t_')); // string(70) "/Users/zhangyue/MyDoc/博客文章/dev-blog/php/202010/source/t_Gx6S5d"


$temp = tmpfile();
fwrite($temp, "writing to tempfile");
fseek($temp, 0);
// sleep(30); // /tmp/phpU2LZ3V 文件
echo fread($temp, 1024), PHP_EOL; // writing to tempfile
fclose($temp); // 文件直接被刪除了

tempnam() 函數(shù)會根據(jù)指定的 prefix 參數(shù)來生成一個隨機不重名的空文件。在測試代碼中,我們給定的 prefix 的值是 t_ ,最后生成的文件就是 t_Gx655d 這樣一個空的文件。

tmpfile() 在之前的文章中也講解過,它是生成一個臨時文件,一般會放在 /tmp 目錄下(如果你沒有修改 php.ini 文件中的相關設置的話)。這個函數(shù)創(chuàng)建文件后會返回一個句柄,一旦使用 fclose() 關閉了這個文件句柄,那么文件就馬上會被刪除掉。

按規(guī)則返回目錄內容

foreach (glob("*.txt"as $filename) {
    echo "$filename size: " . filesize($filename) , PHP_EOL;
}
// cp_test.txt size 8
// fpc_test.txt size 8
// ltest.txt size 8
// ltest2.txt size 8
// new_re_test.txt size 8
// test.txt size 8
// test3.txt size 0

foreach (glob("../../202009/*.md"as $filename) {
    echo "$filename size: " . filesize($filename) , PHP_EOL;
}
// ./../202009/1.PHP中的PDO操作學習(三)預處理類及綁定數(shù)據(jù).md size:16881
// ../../202009/10.PHP中非常好玩的Calendar擴展學習.md size:8784
// ../../202009/11.學習PHP中的國際化功能來查看貨幣及日期信息.md size:5521
// ../../202009/12.PHP中的日期相關函數(shù)(一).md size:14217
// ../../202009/13.PHP中的日期相關函數(shù)(二).md size:9858
// ../../202009/2.PHP中的PDO操作學習(四)查詢結構集.md size:12825
// ../../202009/3.在PHP中使用SPL庫中的對象方法進行XML與數(shù)組的轉換.md size:6068
// ../../202009/4.PHP中的MySQLi擴展學習(一)MySQLi介紹.md size:6029
// ../../202009/5.PHP中的MySQLi擴展學習(二)mysqli類的一些少見的屬性方法.md size:9726
// ../../202009/6.PHP中的MySQLi擴展學習(三)mysqli的基本操作.md size:9403
// ../../202009/7.PHP中的MySQLi擴展學習(四)mysqli的事務與預處理語句.md size:3556
// ../../202009/8.PHP中的MySQLi擴展學習(五)MySQLI_STMT對象操作.md size:7450
// ../../202009/9.PHP中的MySQLi擴展學習(六)MySQLI_result對象操作.md size:10650

glob 函數(shù)也是之前有講解過的一個函數(shù),它會根據(jù)指定的規(guī)則返回目錄中的所有文件或者目錄信息。可以方便地用于目錄地遍歷操作。注意這里的規(guī)則參數(shù)不是完全的正則表達式,關于它具體支持的語法可以自行查閱相關的文檔。

文件 umask 操作

$old = umask(0);
echo $old, PHP_EOL; // 18
$now = umask();
echo $now, PHP_EOL; // 0

umask() 函數(shù)就是操作當前執(zhí)行進程的 umask 信息,和 Linux 中的 umask 命令一樣,用于指定當前創(chuàng)建的目錄文件的默認權限信息。在 PHP 中,umask() 將 PHP 的 umask 設定為 mask & 0777 ,并返回原來的 umask 。當 PHP 被作為服務器模塊使用時,在每個請求結束后 umask 會被恢復。具體的 umask 知識大家可以參考 Linux 中的相關內容。

配置文件信息讀取

最后這兩個函數(shù)是用于讀取 PHP 類型的配置文件信息的,什么叫 PHP 類型的配置文件信息?其實就是類似于 php.ini 文件那樣的配置文件,key=value 這種形式的配置文件。就像 Laravel 的 .env 文件也是可以使用這兩個函數(shù)進行讀取的。

var_dump(parse_ini_file('/usr/local/etc/php/7.3/php.ini'));
// array(133) {
//     ["#zend_extension"]=>
//     string(9) "xdebug.so"
//     ["extension"]=>
//     string(6) "vld.so"
//     ["engine"]=>
// ……
// ……

var_dump(parse_ini_file('/usr/local/etc/php/7.3/php.ini'true));
// array(38) {
//     ["#zend_extension"]=>
//     string(9) "xdebug.so"
//     ["extension"]=>
//     string(6) "vld.so"
//     ["PHP"]=>
//     array(45) {
//       ["engine"]=>
//       string(1) "1"
//       ["short_open_tag"]=>
// ……
// ……

parse_ini_file() 函數(shù)就是直接讀取指定路徑的配置文件內容,在這里我們直接測試的就是讀取 php.ini 文件。它有一個可選參數(shù),如果設置為 true 的話,返回的就是數(shù)組分類的結構化的內容。

$ini = file_get_contents('/usr/local/etc/php/7.3/php.ini');
var_dump(parse_ini_string($ini));
// array(133) {
//     ["#zend_extension"]=>
//     string(9) "xdebug.so"
//     ["extension"]=>
//     string(6) "vld.so"
//     ["engine"]=>
// ……
// ……

var_dump(parse_ini_string($ini, true));
// array(38) {
//     ["#zend_extension"]=>
//     string(9) "xdebug.so"
//     ["extension"]=>
//     string(6) "vld.so"
//     ["PHP"]=>
//     array(45) {
//       ["engine"]=>
//       string(1) "1"
//       ["short_open_tag"]=>
// ……
// ……

parse_ini_string() 則是從給定的字符串中讀取配置信息,同樣也有一個格式化分組輸出的參數(shù)可選。它和 parse_ini_file() 是完全相同的,唯一的區(qū)別就是一個是從文件路徑讀取,一個是從字符串讀取。

總結

一口氣介紹了這么多函數(shù),大家是不是都用過呢?有人要說了,寫這玩意干嘛,直接去看文檔不就好了嘛?那可不一樣哦,文檔中很多函數(shù)的介紹就一句話,示例代碼也都是使用英文注釋的,咱這雖說也是一個搬運工,但咱不僅是簡單地搬運了一下,還把例子重寫了,另外還加上了一些應用場景的介紹哦!至于各位看官感覺好不好,那就仁者見仁,智者見智咯!

測試代碼:

https://github.com/zhangyue0503/dev-blog/blob/master/php/202010/source/7.PHP中的文件系統(tǒng)函數(shù)(二).php

參考文檔:

https://www./manual/zh/ref.filesystem.php

    轉藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多