php的各種 I/O流 以及用法

  • 2019 年 12 月 19 日
  • 筆記

php://協議

首先,我們來說一下一個php提供的協議:"php://"

或許有人看到這個會懵逼,這是什麼東東?這有啥用?這咋用?我是誰?我在哪?我要去往何處?

恩,大家可以翻開php手冊,搜索一下 

php://是php內置的一個類url操作的協議,它運行我們訪問php各種I/O流,至於什麼是I/O流,舉個例子:

echo "hello world";  這個字元串會經過php的處理,最後輸出到用戶端/控制台,而這個就是"hello world"就是  輸出的 流,程式把這個字元串處理成一串串的二進位,輸出到了用戶端/控制台,這樣的字元串就叫做輸出流

同理,用戶發起一個post請求,將數據傳給伺服器,伺服器接收,這樣的字元串就叫做輸入流

好了,該協議的用法先放著,我們來看看php的各種I/O流

STDIN  輸入流

STDIN輸入流為 php的標準輸入流,一般是指鍵盤輸入到程式緩衝區的數據 在php中,主要是指在php-cli運行模式下,用戶使用鍵盤輸入到控制台的數據,例如:(注意,需要使用php-cli模式)

<?php  /**   * Created by PhpStorm.   * User: tioncico   * Date: 18-10-20   * Time: 下午5:20   */  echo "請輸入你的名字:n";  $stdin = fopen("php://stdin",'r');  $data = fgets($stdin);  echo "{$data}大哥,你好啊!";

可看到,上面使用了php://stdin 協議,打開了一個標準輸入的操作句柄,然後可讀取用戶在控制台輸入的數據

上面的程式碼也可寫成:

<?php  /**   * Created by PhpStorm.   * User: tioncico   * Date: 18-10-20   * Time: 下午5:20   */  echo "請輸入你的名字:n";  $data = trim(fgets(STDIN));  echo "{$data}大哥,你好啊!";

STDIN常量是一個已經打開的stdin流,可節省幾行程式碼,也可節省小部分打開stdin的性能

當然,值得注意的點是:

1:php://stdin打開的其實是STDIN常量已經打開的複製,所以就算關閉了php://stdin,也是關閉的複製,STDIN已打開的不會被關閉

2:php://stdin是只讀的

3:請直接使用STDIN常量,而不使用php://stdin

4:使用fgets讀取,只能讀取一行數據(檢測到回車就返回),可以使用stream_get_contents 控制讀取數量,用於一次性讀取包含換行的輸入數據

STDOUT輸出流

STDOUT和STDIN正好相反,是標準輸出流,它將運行php將字元串默認輸出到控制台(可使用freopen重定向到文件),例如:(注意,使用php-cli模式運行)

<?php  /**   * Created by PhpStorm.   * User: tioncico   * Date: 18-10-20   * Time: 下午5:20   */  $stdout = fopen("php://stdout",'w');  fwrite($stdout,"這是輸出1n");  echo "這是輸出2n";  fwrite(STDOUT,"這是輸出3n");

和stdin注意點一樣,這裡不複製了,但需要加上一條:

在php-cli模式中,作用和echo相同,但是實現方式不一樣

STDERR 標準錯誤

STRERR 標準錯誤和STDOUT差不多,都是將字元串默認列印到控制台(可使用freopen重定向到文件),但是這個是列印錯誤用的,區分就是STDERR會將列印的字元串變成紅色(需要終端支援)例如:(注意,使用php-cli模式運行)

<?php  /**   * Created by PhpStorm.   * User: tioncico   * Date: 18-10-20   * Time: 下午5:20   */  $stderr = fopen("php://stderr",'w');  fwrite($stderr,"這是輸出1n");  echo "這是輸出2n";  fwrite(STDERR,"這是輸出3n");  $a=$b;

從上面的STDOUT注意點到這裡可以發現,STDERR和echo語句的輸出順序是不相同的,個人猜測是echo的緩衝區和STDERR不相同

php://input

從這裡開始,就和上面的3個程式標準I/O流關係不大啦,咱們繼續往下看,該部分參考:http://www.nowamagic.net/academy/detail/12220520,有時間可詳細閱讀,本文只做功能簡單介紹

php://input 是個可以訪問請求的原始數據的只讀流。

通俗來講:php://input可接收用戶請求過來的原始數據流(大多數時候作用於POST請求),例如:(需要使用web方式請求)

服務端程式碼:

<?php  $data = file_get_contents("php://input",'r');  echo "下面是php://inputn";  var_dump($data);  echo 1;  echo "下面是 POST:n";  var_dump($_POST);

客戶端請求程式碼:

<?php  /**   * Created by PhpStorm.   * User: tioncico   * Date: 18-10-27   * Time: 下午11:06   */    function send_post($url, $post_data) {        $postdata = http_build_query($post_data);      $options = array(          'http' => array(              'method' => 'POST',              'header' => 'Content-type:application/x-www-form-urlencoded',              'content' => $postdata,              'timeout' => 15 * 60 // 超時時間(單位:s)          )      );      $context = stream_context_create($options);      $result = file_get_contents($url, false, $context);      return $result;  }    //使用方法  $post_data = array(      'username' => 'tioncico',      'password' => '123456'  );  $data = send_post('http://test.cn', $post_data);  var_dump($data);

輸出:

php://output

php://output 是一個只寫的數據流, 允許你以 print 和 echo 一樣的方式 寫入到輸出緩衝區。可以說功能和echo 一樣(可以在web和php-cli使用)

<?php  file_put_contents("php://output","仙士可最帥");

php://fd

php://fd 允許直接訪問指定的文件描述符。 例如 php://fd/3 引用了文件描述符 3。用法:

在linux中,一切皆文件,當啟動系統時,先會啟動STDIN標準輸入(文件描述符0),之後是STDOUT文件描述符1,STDERR文件描述符2 使用php://fd,可直接調用該文件:

<?php  $stdin = fopen("php://fd/0",'r');  $data = fgets($stdin);  echo "這是STDIN輸入的:{$data}n";  file_put_contents("php://fd/2","這是STDERRn");  file_put_contents("php://fd/1","這是STDOUTn");

php://memory 和 php://temp

php://memory 和 php://temp 是一個類似文件 包裝器的數據流,允許讀寫臨時數據。 兩者的唯一區別是 php://memory 總是把數據儲存在記憶體中, 而 php://temp 會在記憶體量達到預定義的限制後(默認是 2MB)存入臨時文件中。 臨時文件位置的決定和 sys_get_temp_dir() 的方式一致。 php://temp 的記憶體限制可通過添加 /maxmemory:NN 來控制,NN 是以位元組為單位、保留在記憶體的最大數據量,超過則使用臨時文件。例如:

<?php  // Set the limit to 5 MB.  $fiveMBs = 5 * 1024 * 1024;  $temp_f = fopen("php://temp/maxmemory:$fiveMBs", 'r+');//maxmemory可以調整存儲空間大小  fputs($temp_f, "hello,仙士可,我是temp的數據n");  rewind($temp_f);//由於寫入數據時,指針已經到了末尾,需要重置指針才能讀取到數據  echo stream_get_contents($temp_f);  $fiveMBs = 5 * 1024 * 1024;  $memory_f = fopen("php://memory", 'r+');//maxmemory可以調整存儲空間大小  fputs($memory_f, "hello,仙士可,我是memory的數據nn");  rewind($memory_f);//由於寫入數據時,指針已經到了末尾,需要重置指針才能讀取到數據  echo stream_get_contents($memory_f);

注意:關閉文件之後數據將無法讀取

php://filter

php://filter 是一種元封裝器, 設計用於數據流打開時的篩選過濾應用。 這對於一體式(all-in-one)的文件函數非常有用,類似 readfile()、 file() 和 file_get_contents(), 在數據流內容讀取之前沒有機會應用其他過濾器。

php://filter 目標使用以下的參數作為它路徑的一部分。 複合過濾鏈能夠在一個路徑上指定。詳細使用這些參數可以參考具體範例。

名稱

描述

resource=<要過濾的數據流>

這個參數是必須的。它指定了你要篩選過濾的數據流。

read=<讀鏈的篩選列表>

該參數可選。可以設定一個或多個過濾器名稱,以管道符(|)分隔。

write=<寫鏈的篩選列表>

該參數可選。可以設定一個或多個過濾器名稱,以管道符(|)分隔。

<;兩個鏈的篩選列表>

任何沒有以 read= 或 write= 作前綴 的篩選器列表會視情況應用於讀或寫鏈。

可選項

屬性

支援

受限於 allow_url_fopen

No

受限於 allow_url_include

僅 php://input、 php://stdin、 php://memory 和 php://temp。

允許讀取

僅 php://stdin、 php://input、 php://fd、 php://memory 和 php://temp。

允許寫入

僅 php://stdout、 php://stderr、 php://output、 php://fd、 php://memory 和 php://temp。

允許追加

僅 php://stdout、 php://stderr、 php://output、 php://fd、 php://memory 和 php://temp(等於寫入)

允許同時讀寫

僅 php://fd、 php://memory 和 php://temp。

支援 stat()

僅 php://memory 和 php://temp。

支援 unlink()

No

支援 rename()

No

支援 mkdir()

No

支援 rmdir()

No

僅僅支援 stream_select()

php://stdin、 php://stdout、 php://stderr、 php://fd 和 php://temp。

該協議個人不是很會用,並且個人覺得沒啥必要學習,所以直接複製php手冊的例子吧

<?php  /* 這會以大寫字母輸出 www.example.com 的全部內容 */  readfile("php://filter/read=string.toupper/resource=http://www.example.com");    /* 這會和以上所做的一樣,但還會用 ROT13 加密。 */  readfile("php://filter/read=string.toupper|string.rot13/resource=http://www.example.com");

本文為仙士可原創文章,轉載無需和我聯繫,但請註明來自仙士可部落格www.php20.cn