PHP七天系列之文件與目錄

PHP提供了完善的操作文件與目錄機(jī)制碍沐。

基礎(chǔ)函數(shù)


disk_total_space

本函數(shù)返回的是該目錄所在的磁盤分區(qū)的總大小,因此在給出同一個(gè)磁盤分區(qū)的不同目錄作為參數(shù)所得到的結(jié)果完全相同雪猪。

disk_free_space

參數(shù)是一個(gè)目錄的字符串绰寞。該函數(shù)將根據(jù)相應(yīng)的文件系統(tǒng)或磁盤分區(qū)返回可用的字節(jié)數(shù)撮竿。

自動(dòng)添加單位

/**
 * 獲取有單位的大小
 * @param int $total 大小單位字節(jié)
 * @return string|null
 */
function space_total(int $total): ?string
{
    $config = [3 => 'GB', 2 => 'MB', 1 => 'KB'];
    foreach ($config as $num => $unit) {
        if ($total > pow(1024, $num)) {
            return round($total / pow(1024, $num)) . $unit;
        }
    }
    return '0KB';
}

echo space_total(disk_total_space('.'));

filesize

取得指定文件的大小纤泵。

$filename = 'somefile.txt';
echo $filename . ': ' . filesize($filename) . ' bytes';

fopen

打開文件或者 URL骆姐。如果打開的是URL需要保證PHP.INI配置項(xiàng)allow_url_fopen 開啟。
在操作二進(jìn)制文件時(shí)如果沒(méi)有指定 'b' 標(biāo)記捏题,可能會(huì)碰到一些奇怪的問(wèn)題玻褪,包括壞掉的圖片文件以及關(guān)于 \r\n 字符的奇怪問(wèn)題。

mode 說(shuō)明
'r' 只讀方式打開公荧,將文件指針指向文件頭带射。
'r+' 讀寫方式打開,將文件指針指向文件頭循狰。
'w' 寫入方式打開窟社,將文件指針指向文件頭并將文件大小截為零。如果文件不存在則嘗試創(chuàng)建之绪钥。
'w+' 讀寫方式打開桥爽,將文件指針指向文件頭并將文件大小截為零。如果文件不存在則嘗試創(chuàng)建之昧识。
'a' 寫入方式打開,將文件指針指向文件末尾盗扒。如果文件不存在則嘗試創(chuàng)建之跪楞。
'a+' 讀寫方式打開,將文件指針指向文件末尾侣灶。如果文件不存在則嘗試創(chuàng)建之甸祭。
'x' 創(chuàng)建并以寫入方式打開,將文件指針指向文件頭褥影。如果文件已存在池户,則 fopen() 調(diào)用失敗并返回 FALSE,并生成一條 E_WARNING 級(jí)別的錯(cuò)誤信息。如果文件不存在則嘗試創(chuàng)建之校焦。
'x+' 創(chuàng)建并以讀寫方式打開赊抖,其他的行為和 'x' 一樣。

fread

返回所讀取的字符串寨典, 或者在失敗時(shí)返回 FALSE氛雪。

$filename = 'a.txt';
$handle = fopen($filename,'r');
echo fread($handle,filesize($filename));

fseek

在文件指針中定位,注意移動(dòng)到 EOF 之后的位置不算錯(cuò)誤耸成。

$filename = 'a.txt';//a.txt內(nèi)容為 abc
$handle = fopen($filename, 'r+');
fseek($handle, 1);
//移動(dòng)指針后讀取為bc
echo fread($handle, filesize($filename));

fwrite

寫入文件报亩,返回寫入的字符數(shù),出現(xiàn)錯(cuò)誤時(shí)則返回 FALSE 弦追。
在區(qū)分二進(jìn)制文件和文本文件的系統(tǒng)上(如 Windows) 打開文件時(shí),fopen() 函數(shù)的 mode 參數(shù)要加上 'b'劲件。

$handle = fopen('pf.txt','r+');
fwrite($handle,'aa');
fseek($handle,0);
echo fread($handle,999);

fclose

fclose — 關(guān)閉一個(gè)已打開的文件指針

$handle = fopen('somefile.txt', 'r');
fclose($handle);

feof

測(cè)試文件指針是否到了文件結(jié)束的位置

$handle = fopen('pf.txt','rb');
while(!feof($handle)){
    echo fread($handle,1);
}

fgetc

讀取一個(gè)字符

$handle = fopen('pf.txt','rb');
while($c = fgetc($handle))
echo $c;

fgets

讀取一行內(nèi)容

$handle = fopen('pf.txt','rb');
while($c = fgets($handle))
echo $c;

fgetss

從文件指針中讀取一行并過(guò)濾掉 HTML 標(biāo)記左胞。
參數(shù)分別表示:資源對(duì)象、讀取數(shù)量烤宙、允許標(biāo)簽。

$handle = fopen('pf.html','rb');
while(!feof($handle)){
    echo fgetss($handle,20,'<h1><title>');
}

fgetcsv

從文件指針中讀入一行并解析 CSV 字段躺枕。

$handle = fopen('user.csv','rb');
$users = fgetcsv($handle,0,',');
print_r($users);

readfile

讀取文件所有內(nèi)容

<?php
header('Content-type:image/jpeg');
readfile('user.jpeg');

flock

鎖定文件操作,如果使用flock 鎖定文件拐云,必須保證在所有使用文件地方執(zhí)行 flock 才有意義。如果過(guò)早的系統(tǒng)因?yàn)椴恢С宙i定操作膳帕,函數(shù)執(zhí)行將沒(méi)有效果如FAT系統(tǒng)。

鎖定方式 說(shuō)明
LOCK_SH 取得共享鎖定(讀取的程序)
LOCK_EX 取得獨(dú)占鎖定(寫入的程序)
LOCK_UN 釋放鎖定(無(wú)論共享或獨(dú)占)
LOCK_NB 無(wú)法建立鎖定時(shí)危彩,此操作可不被阻斷,馬上返回進(jìn)程汤徽。通常與LOCK_SH或LOCK_EX 做OR組合使用。(Windows 系統(tǒng)上還不支持)

讀鎖

1.php 文件內(nèi)容:

<?php
$handle = fopen('pf.txt','rb');
$stat = flock($handle,LOCK_SH);
sleep(5);
echo fgetss($handle);
flock($handle,LOCK_UN);

2.php

<?php
$handle = fopen('pf.txt','rb');
$stat = flock($handle,LOCK_SH);
echo fgetss($handle);
flock($handle,LOCK_UN);

讀鎖不能寫入文件可以讀取文件灸撰,并不會(huì)阻塞谒府。

寫鎖

1.php 文件內(nèi)容:

<?php
$handle = fopen('pf.txt','rb');
$stat = flock($handle,LOCK_EX);
sleep(5);
echo fgetss($handle);
flock($handle,LOCK_UN);

2.php

<?php
$handle = fopen('pf.txt','rb');
$stat = flock($handle,LOCK_SH);
echo fgetss($handle);
flock($handle,LOCK_UN);

寫鎖為獨(dú)占拼坎,所以讀取文件也會(huì)阻塞,前一個(gè)文件執(zhí)行完后才可以執(zhí)行第二個(gè)完疫。

防止阻塞

1.php

<?php
$handle = fopen('pf.txt','ab');
$stat = flock($handle,LOCK_EX);
sleep(5);
echo fgetss($handle);

flock($handle,LOCK_UN);

2.php

<?php
$handle = fopen('pf.txt','ab');
$stat = flock($handle,LOCK_SH | LOCK_NB,$wouldblock);
if($stat){
    $d = fwrite($handle,'aoxiangjun.com');
    echo fgetss($handle);
}else{
    echo 'file is locked';
}
flock($handle,LOCK_UN);
  • 使用LOCK_NB當(dāng)文件被其他請(qǐng)求鎖定時(shí)泰鸡,腳本繼續(xù)向下執(zhí)行,鎖定失敗趋惨。
  • 阻塞時(shí) $wouldblock 亦是為真

is_writable

判斷給定的文件名是否可寫

<?php
$filename = 'test.txt';
if (is_writable($filename)) {
    echo 'The file is writable';
} else {
    echo 'The file is not writable';
}

is_readable

判斷給定文件名是否可讀

<?php
$filename = 'test.txt';
if (is_readable($filename)) {
    echo 'The file is readable';
} else {
    echo 'The file is not readable';
}

file_exists

檢查文件或目錄是否存在

<?php
$filename = '/path/to/foo.txt';

if (file_exists($filename)) {
    echo "The file $filename exists";
} else {
    echo "The file $filename does not exist";
}

is_file

判斷給定文件名是否為一個(gè)正常的文件鸟顺。

is_dir

判斷給定文件名是否是一個(gè)目錄。

filesize

取得指定文件的大小器虾,返回文件大小的字節(jié)數(shù)讯嫂。

echo filesize('pf.txt');

file_put_contents

將一個(gè)字符串寫入文件。

參數(shù) 說(shuō)明
參數(shù)一 文件名
參數(shù)二 寫入的字符串
參數(shù)三 FILE_APPEND:如果文件 filename 已經(jīng)存在兆沙,追加數(shù)據(jù)而不是覆蓋欧芽。LOCK_EX:在寫入時(shí)獲得一個(gè)獨(dú)占鎖。

file_get_content

將整個(gè)文件讀入一個(gè)字符串葛圃,如果打開遠(yuǎn)程文件需要開啟php.ini中的 allow_url_fopen 選項(xiàng)千扔。

filemtime

本函數(shù)返回文件中的數(shù)據(jù)塊上次被寫入的時(shí)間,也就是說(shuō)库正,文件的內(nèi)容上次被修改的時(shí)間曲楚。
下面是緩存文件的操作代碼,實(shí)際開發(fā)中的緩存控制還要注意很多細(xì)節(jié)褥符,下面是核心思路代碼龙誊。

<?php
//緩存文件存在并且沒(méi)有過(guò)期時(shí)使用緩存文件
if (is_file('1.cache.php') && filemtime('1.cache.php') > (time() - 10)) {
    include '1.cache.php';
} else {
    //開啟緩存區(qū)并保存解析數(shù)據(jù)到緩存文件
    ob_start();
    include '1.blade.php';
    $content = ob_get_clean();
    echo $content;
    file_put_contents('1.cache.php', $content);
}

var_export

輸出或返回一個(gè)變量的字符串表示。

下面是將數(shù)組保存到文件中的代碼喷楣,并支持include 獲取數(shù)組數(shù)據(jù)趟大。

<?php
$user = [
    ['name'=>'PF大叔'],
    ['name'=>'小明']
];
$content =var_export($user,true);
file_put_contents('users.php','<?php return '.$content.';');

basename

返回路徑中的文件名部分

echo basename(__FILE__);

dirname

返回路徑中的目錄部分

echo dirname(__FILE__);

mkdir

支持遞歸的目錄創(chuàng)建,參數(shù)分別是:目錄铣焊、權(quán)限位逊朽、遞歸創(chuàng)建

mkdir('a/b/c',0755,true);

rmdir

刪除指定的目錄,該目錄必須是空的曲伊,而且要有相應(yīng)的權(quán)限叽讳。

rmdir('views');

rename

重命名一個(gè)文件或目錄,也可以進(jìn)行文件移動(dòng)坟募。

// 將1.html更名為a.html
rename('1.html','a.html');

//移動(dòng)文件1.html到目錄PFinal中
rename('1.html','PFinal/1.html');

copy

復(fù)制文件

//復(fù)制1.blade.php到目錄f中
copy('1.blade.php','f/1.blade.php');

常用常量

__DIR__

獲取文件所有目錄。

__FILE__

獲取文件的完整路徑,包含文件名昂利。

DIRECTORY_SEPARATOR

目錄分隔符,在 Windows 中蜂奸,斜線(/)和反斜線(\)都可以用作目錄分隔符扩所,但是在linux上使用(/),此常量會(huì)自動(dòng)根據(jù)系統(tǒng)設(shè)置為合適的分隔符助赞。

文件遍歷

opendir

opendir 函數(shù)類似于 fopen 操作方式雹食,可能獲取目錄指針讀取目錄群叶,下面是操作示例街立。

$handle = opendir('../php');
while (false!==($file = readdir($handle))) {
    if (!in_array($file, ['.','..'])) {
        echo filetype($file)."\t".$file.'<br/>';
    }
}
closedir($handle);

scandir
列出指定路徑中的文件和目錄赎离。

foreach (scandir('../php') as $file) {
    if (!in_array($file, ['.','..'])) {
        echo filetype($file)."\t\t".$file.'<hr/>';
    }
}

glob使用

尋找與模式匹配的文件路徑植阴。
參數(shù)順序?yàn)椋簠?shù)一文件路徑掠手,參數(shù)二選項(xiàng)標(biāo)記

下面是常用選項(xiàng)標(biāo)記

選項(xiàng) 說(shuō)明
GLOB_MARK 在每個(gè)返回的項(xiàng)目中加一個(gè)斜線
GLOB_NOSORT 按照文件在目錄中出現(xiàn)的原始順序返回(不排序)
GLOB_NOCHECK 如果沒(méi)有文件匹配則返回用于搜索的模式
GLOB_ERR 停止并讀取錯(cuò)誤信息(比如說(shuō)不可讀的目錄)众雷,默認(rèn)的情況下忽略所有錯(cuò)誤
GLOB_BRACE 設(shè)置多個(gè)匹配模式做祝,如:{.php,.txt}

遍歷目錄

$files = glob('../../*');
print_r($files);

指定檢索文件類型

$files = glob('*.php', GLOB_ERR);

設(shè)置多個(gè)匹配模式

$files = glob("{*.php,*.txt}", GLOB_BRACE);
print_r($files);

目錄大小

function dirSize($dir):int
{
    $size= 0;
    foreach (glob($dir.'/*') as $file) {
        $size += is_file($file)?filesize($file):dirSize($file);
    }
    return $size;
}
echo round(dirSize('/home/vagrant')/1024/1024).'MB';

刪除目錄

function delDir($dir):bool
{
    if (!is_dir($dir)) {
        return true;
    }
    foreach (glob($dir.'/*') as $file) {
        is_file($file)?unlink($file):delDir($file);
    }
    return rmdir($dir);
}
delDir('../php2');

復(fù)制目錄

function copyDir($dir, $to):bool
{
    is_dir($to) or mkdir($to, 0755, true);
    foreach (glob($dir.'/*') as $file) {
        $target = $to.'/'.basename($file);
        is_file($file)?copy($file, $target):copyDir($file, $target);
    }
    return true;
}
copyDir('../php', '../php2');

移動(dòng)目錄

移動(dòng)目錄分兩步執(zhí)行编兄,第一步是復(fù)制目錄狠鸳,第二步是刪除目錄,所以使用上面兩個(gè)函數(shù)的綜合即可以卸察。

function moveDir($dir, $to):bool
{
    copyDir($dir, $to);
    return delDir($dir);
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末坑质,一起剝皮案震驚了整個(gè)濱河市涡扼,隨后出現(xiàn)的幾起案子壳澳,更是在濱河造成了極大的恐慌茫经,老刑警劉巖卸伞,帶你破解...
    沈念sama閱讀 219,589評(píng)論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件荤傲,死亡現(xiàn)場(chǎng)離奇詭異遂黍,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)铃彰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,615評(píng)論 3 396
  • 文/潘曉璐 我一進(jìn)店門牙捉,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)邪铲,“玉大人带到,你說(shuō)我怎么就攤上這事英染。” “怎么了永丝?”我有些...
    開封第一講書人閱讀 165,933評(píng)論 0 356
  • 文/不壞的土叔 我叫張陵慕嚷,是天一觀的道長(zhǎng)喝检。 經(jīng)常有香客問(wèn)我挠说,道長(zhǎng)损俭,這世上最難降的妖魔是什么潘酗? 我笑而不...
    開封第一講書人閱讀 58,976評(píng)論 1 295
  • 正文 為了忘掉前任琐脏,我火速辦了婚禮缸兔,結(jié)果婚禮上惰蜜,老公的妹妹穿的比我還像新娘。我一直安慰自己政钟,他們只是感情好养交,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,999評(píng)論 6 393
  • 文/花漫 我一把揭開白布碎连。 她就那樣靜靜地躺著鱼辙,像睡著了一般。 火紅的嫁衣襯著肌膚如雪怠噪。 梳的紋絲不亂的頭發(fā)上杜跷,一...
    開封第一講書人閱讀 51,775評(píng)論 1 307
  • 那天葛闷,我揣著相機(jī)與錄音淑趾,去河邊找鬼。 笑死近范,一個(gè)胖子當(dāng)著我的面吹牛延蟹,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播稚照,決...
    沈念sama閱讀 40,474評(píng)論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼果录,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼弱恒!你這毒婦竟也來(lái)了棋恼?” 一聲冷哼從身側(cè)響起爪飘,我...
    開封第一講書人閱讀 39,359評(píng)論 0 276
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎默终,沒(méi)想到半個(gè)月后齐蔽,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,854評(píng)論 1 317
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡诱渤,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 38,007評(píng)論 3 338
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了鸦做。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片泼诱。...
    茶點(diǎn)故事閱讀 40,146評(píng)論 1 351
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡治筒,死狀恐怖耸袜,靈堂內(nèi)的尸體忽然破棺而出牲平,到底是詐尸還是另有隱情,我是刑警寧澤蜈抓,帶...
    沈念sama閱讀 35,826評(píng)論 5 346
  • 正文 年R本政府宣布沟使,位于F島的核電站腊嗡,受9級(jí)特大地震影響拾酝,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜棺亭,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,484評(píng)論 3 331
  • 文/蒙蒙 一镶摘、第九天 我趴在偏房一處隱蔽的房頂上張望凄敢。 院中可真熱鬧,春花似錦扑庞、人聲如沸拒逮。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,029評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)玩徊。三九已至恩袱,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間潭辈,已是汗流浹背澈吨。 一陣腳步聲響...
    開封第一講書人閱讀 33,153評(píng)論 1 272
  • 我被黑心中介騙來(lái)泰國(guó)打工技竟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留榔组,地道東北人。 一個(gè)月前我還...
    沈念sama閱讀 48,420評(píng)論 3 373
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像包归,于是被迫代替她去往敵國(guó)和親。 傳聞我的和親對(duì)象是個(gè)殘疾皇子椎椰,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 45,107評(píng)論 2 356

推薦閱讀更多精彩內(nèi)容