熱點推薦:
您现在的位置: 電腦知識網 >> 編程 >> PHP編程 >> 正文

用 PHP 讀取文件的正確方法

2013-11-15 12:22:05  來源: PHP編程 
    了解如何使用 PHP 的各種文件函數查看諸如 fopenfclose 和 feof 之類的基本文件函數了解諸如 fgetsfgetss 和 fscanf 之類的讀取函數並且發現用一兩行代碼處理整個文件的函數

  讓我們算一算有多少種方法

  處理諸如 PHP 之類的現代編程語言的樂趣之一就是有大量的選項可用PHP 可以輕松地贏得 Perl 的座右銘Theres more than one way to do it(並非只有一種方法可做這件事)尤其是在文件處理上但是在這麼多可用的選項中哪一種是完成作業的最佳工具?當然實際答案取決於解析文件的目標因此值得花時間探究所有選項

  傳統的 fopen 方法

  fopen 方法可能是以前的 C 和 C++ 程序員最熟悉的因為如果您使用過這些語言那麼它們或多或少都是您已掌握多年的工具對於這些方法中的任何一種通過使用 fopen(用於讀取數據的函數)的標准方法打開文件然後使用 fclose 關閉文件如清單 所示

  清單 用 fgets 打開並讀取文件

  $file_handle = fopen(myfile r); while (!feof($file_handle)) { $line = fgets($file_handle); echo $line; } fclose($file_handle);


  雖然大多數具有多年編程經驗的程序員都熟悉這些函數但是讓我對這些函數進行分解有效地執行以下步驟


    打開文件$file_handle 存儲了一個對文件本身的引用
    檢查您是否已到達文件的末尾
    繼續讀取文件直至到達文件末尾邊讀取邊打印每行
    關閉文件

  記住這些步驟我將回顧在這裡使用的每個文件函數

  fopen

  fopen 函數將創建與文件的連接我之所以說創建連接是因為除了打開文件之外fopen 還可以打開一個 URL

  

  $fh = fopen( r);


  這行代碼將創建一個與以上頁面的連接並允許您開始像讀取一個本地文件一樣讀取它

  注 fopen 中使用的 r 將指示文件以只讀方式打開由於將數據寫入文件不在本文的討論范圍內因此我將不列出所有其他選項但是如果是從二進制文件讀取以獲得跨平台兼容性則應當將 r 更改為 rb稍後您將看到這樣的示例

  feof

  feof 命令將檢測您是否已經讀到文件的末尾並返回 True 或 False清單 中的循環將繼續執行直至您達到文件myfile的末尾如果讀取的是 URL 並且套接字由於不再有任何數據可以讀取而超時則 feof 也將返回 False

  fclose

  向前跳至清單 的末尾fclose 將實現與 fopen 相反的功能它將關閉指向文件或 URL 的連接執行此函數後您將不再能夠從文件或套接字中讀取任何信息

  fgets

  在清單 中回跳幾行您就到達了文件處理的核心實際讀取文件fgets 函數是處理第一個示例的首選武器它將從文件中提取一行數據並將其作為字符串返回在那之後您可以打印或者以別的方式處理數據清單 中的示例將精細地打印整個文件

  如果決定限制處理數據塊的大小您可以將一個參數添加到 fgets 中限制最大行長度例如使用以下代碼將行長度限制為 個字符

  

  $string = fgets($file_handle );


  回想 C 中的\字符串末尾終止符將長度設為比實際所需值大一的數字因而如果需要 個字符則以上示例使用 應養成以下習慣只要對此函數使用行限制就添加該額外字符

  fread

  fgets 函數是多個文件讀取函數中惟一一個可用的它是一個更常用的函數因為逐行解析通常會有意義事實上幾個其他函數也可以提供類似功能但是您並非總是需要逐行解析

  這時就需要使用 freadfread 函數與 fgets 的處理目標略有不同它趨於從二進制文件(即並非主要包含人類可閱讀的文本的文件)中讀取信息由於的概念與二進制文件無關(邏輯數據結構通常都不是由新行終止)因此您必須指定需要讀入的字節數

  

  $fh = fopen(myfile rb); $data = fread($file_handle );


使用二進制數據

  注意此函數的示例已經使用了略微不同於 fopen 的參數當處理二進制數據時始終要記得將 b 選項包含在 fopen 中如果跳過這一點Microsoft® Windows® 系統可能無法正確處理文件因為它們將以不同的方式處理新行如果處理的是 Linux® 系統(或其他某個 UNIX® 變種)則這可能看似沒什麼關系但即使不是針對 Windows 開發的這樣做也將獲得良好的跨平台可維護性並且也是應當遵循的一個好習慣

  以上代碼將讀取 字節 ( KB) 的數據不管指定多少字節fread 都不會讀取超過 個字節 ( KB)

  假定文件大小不超過 KB則以下代碼應當能將整個文件讀入一個字符串

  

  $fh = fopen(myfile rb); $data = fread($fh filesize(myfile)); fclose($fh);


  如果文件長度大於此值則只能使用循環將其余內容讀入

  fscanf

  回到字符串處理fscanf 同樣遵循傳統的 C 文件庫函數如果您不熟悉它則 fscanf 將把字段數據從文件讀入變量中

  

  list ($field $field $field) = fscanf($fh %s %s %s);


  此函數使用的格式字符串在很多地方都有描述(如 中)故在此不再贅述可以這樣說字符串格式化極為靈活值得注意的是所有字段都放在函數的返回值中(在 C 中它們都被作為參數傳遞

  fgetss

  fgetss 函數不同於傳統文件函數並使您能更好地了解 PHP 的力量該函數的功能類似於 fgets 函數但將去掉發現的任何 HTML 或 PHP 標記只留下純文本查看如下所示的 HTML 文件

  清單 樣例 HTML 文件

  <html> <head><title>My title</title></head> <body> <p>If you understand what Cause there aint no one for to give you no pain means then you listen to too much of the band America</p> </body> </html>


  然後通過 fgetss 函數過濾它

  清單 使用 fgetss

  $file_handle = fopen(myfile r); while (!feof($file_handle)) { echo = fgetss($file_handle); } fclose($file_handle);


  以下是輸出

  

  My title If you understand what Cause there aint no one for to give you no pain means then you listen to too much of the band America


  fpassthru 函數

  無論怎樣讀取文件您都可以使用 fpassthru 將其余數據轉儲到標准輸出通道

  

  fpassthru($fh);


  此外此函數將打印數據因此無需使用變量獲取數據

  非線性文件處理跳躍訪問

  當然以上函數只允許順序讀取文件更復雜的文件可能要求您來回跳轉到文件的不同部分這時就用得著 fseek 了

  

  fseek($fh );


  以上示例將跳轉回文件的開頭如果不需要完全返回 —— 我們可設定返回千字節 —— 然後就可以這樣寫

  

  fseek($fh );


  從 PHP V 開始您有一些其他選項例如如果需要從當前位置向前跳轉 個字節則可以嘗試使用

  

  fseek($fh SEEK_CUR);


  類似地可以使用以下代碼向後跳轉 個字節

  

  fseek($fh SEEK_CUR);


  如果需要向後跳轉至文件末尾前 個字節處則應使用 SEEK_END

  

  fseek($fh SEEK_END);


  在到達新位置後可以使用 fgetsfscanf 或任何其他方法讀取數據

  注不能將 fseek 用於引用 URL 的文件處理

  提取整個文件

  現在我們將接觸到一些 PHP 的更獨特的文件處理功能用一兩行處理大塊數據例如如何提取文件並在 Web 頁面上顯示其全部內容?好的您看到了 fgets 使用循環的示例但是如何能夠使此過程變得更簡單?用 fgetcontents 會使過程超級簡單該方法將把整個文件放入一個字符串中

  

  $my_file = file_get_contents(myfilename); echo $my_file;


  雖然它不是最好的做法但是可以將此命令更簡明地寫為

  

  echo file_get_contents(myfilename);


  本文主要介紹的是如何處理本地文件但是值得注意的是您還可以用這些函數提取回顯和解析其他 Web 頁面

  

  echo file_get_contents();


  此命令等效於

  

  $fh = fopen( r); fpassthru($fh);


  您一定會查看此命令並認為那還是太費力PHP 開發人員同意您的看法因此可以將以上命令縮短為

  

  readfile();


  readfile 函數將把文件或 Web 頁面的全部內容轉儲到默認的輸出緩沖區默認情況下如果失敗此命令將打印錯誤消息要避免此行為(如果需要)請嘗試

  

  @readfile();


  當然如果確實需要解析文件則 file_get_contents 返回的單個字符串可能有些讓人吃不消您的第一反應可能是用 split() 函數將它分解一下

  

  $array = split(\n file_get_contents(myfile));


  但是既然已經有一個很好的函數為您執行此操作為什麼還要這樣大費周章?PHP 的 file() 函數一步即可完成此操作它將返回分為若干行的字符串數組

  

  $array = file(myfile);


  應當注意的是以上兩個示例有一點細微差別雖然 split 命令將刪除新行但是當使用 file 命令(與 fgets 命令一樣)時新行仍將被附加到數組中的字符串上

  但是PHP 的力量還遠不止於此您可以在一條命令中使用 parse_ini_file 解析整個 PHP 樣式的 ini 文件parse_ini_file 命令接受類似清單 所示的文件

  清單 樣例 ini 文件

  

  ; Comment [personal information] name = King Arthur quest = To seek the holy grail favorite color = Blue [more stuff] Samuel Clemens = Mark Twain Caryn Johnson = Whoopi Goldberg

  以下命令將把此文件轉儲為數組然後打印該數組

  

  $file_array = parse_ini_file(holy_grailini); print_r $file_array;


  以下輸出的是結果

  Listing 輸出

  Array ( [name] => King Arthur [quest] => To seek the Holy Grail [favorite color] => Blue [Samuel Clemens] => Mark Twain [Caryn Johnson] => Whoopi Goldberg )


  當然您可能注意到此命令合並了各個部分這是默認行為但是您可以通過將第二個參數傳遞給 parse_ini_file 輕松地修正它process_sections這是一個布爾型變量將 process_sections 設為 True

  

  $file_array = parse_ini_file(holy_grailini true); print_r $file_array;


  並且您將獲得以下輸出

  清單 輸出

  Array ( [personal information] => Array ( [name] => King Arthur [quest] => To seek the Holy Grail [favorite color] => Blue ) [more stuff] => Array ( [Samuel Clemens] => Mark Twain [Caryn Johnson] => Whoopi Goldberg ) )


  PHP 將把數據放入可以輕松解析的多維數組中

  對於 PHP 文件處理來說這只是冰山一角諸如 tidy_parse_file 和 xml_parse 之類的更復雜的函數可以分別幫助您處理 HTML 和 XML 文檔有關這些特殊函數的使用細節請參閱 參考資料如果您要處理那些類型的文件則那些參考資料值得一看但不必過度考慮本文中談到的每種可能遇到的文件類型下面是一些用於處理到目前為止介紹的函數的很好的通用規則

  最佳實踐

  絕不要假定程序中的一切都將按計劃運行例如如果您要查找的文件已被移動該當如何?如果權限已被改變而無法讀取其內容又當如何?您可以通過使用 file_exists 和 is_readable 預先檢查這些問題

  清單 使用 file_exists 和 is_readable

  $filename = myfile; if (file_exists($filename) && is_readable ($filename)) { $fh = fopen($filename r); # Processing fclose($fh); }


  但是在實踐中用這樣的代碼可能太繁瑣了處理 fopen 的返回值更簡單並且更准確

  

  if ($fh = fopen($filename r)) { # Processing fclose($fh); }


  由於失敗時 fopen 將返回 False這將確保僅當文件成功打開後才執行文件處理當然如果文件不存在或者不可讀您可以期望一個負返回值這將使這個檢查可以檢查所有可能遇到的問題此外如果打開失敗可以退出程序或讓程序顯示錯誤消息

  如 fopen 函數一樣file_get_contentsfile 和 readfile 函數都在打開失敗或處理文件失敗時返回 Falsefgetsfgetssfreadfscanf 和 fclose 函數在出錯時也返回 False當然除 fclose 以外您可能已經對這些函數的返回值都進行了處理使用 fclose 時即使文件處理未正常關閉也不會執行什麼操作因此通常不必檢查 fclose 的返回值

  由您來選擇

  PHP 不缺讀取和解析文件的有效方法諸如 fread 之類的典型函數可能在大多數時候都是最佳的選擇或者當 readfile 剛好能滿足任務需要時您可能會發現自己更為 readfile 的簡單所吸引它實際上取決於所要完成的操作

  如果要處理大量數據fscanf 將能證明自己的價值並比使用 file 附帶 split 和 sprintf 命令更有效率相反如果要回顯只做了少許修改的大量文本則使用 filefile_get_contents 或 readfile 可能更合適使用 PHP 進行緩存或者創建權宜的代理服務器時可能就屬於這種情況

  PHP 給您提供了大量處理文件的工具深入了解這些工具並了解哪些工具最適合於要處理的項目您已擁有很多的選擇因此好好地利用它們享受使用 PHP 處理文件的樂趣


From:http://tw.wingwit.com/Article/program/PHP/201311/20816.html
    推薦文章
    Copyright © 2005-2013 電腦知識網 Computer Knowledge   All rights reserved.