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
- 上一篇: C語言網路編程-tcp伺服器實現
- 下一篇: C語言實現插入排序