PHP輸出緩衝控制(Output Control)總結
php 緩衝簡介
其實我對php ob 系列印象還是很模糊,具體怎麼玩的,還不是很瞭解,平時curd,確實對這些內容沒有深入。作為phper 甚是慚愧。網上搜了一通,互相copy,程式碼執行不能出現作者所描述現象,本文良心出品,程式碼都是作者執行過。
當執行輸出的時候,比如 echo,print。輸出並沒有立即送給 web server, 而是將資料寫入 php buffer。php output_buffering 機制好處當然提升效能。其實 php 檔案最終在瀏覽器上顯示,走過3個緩衝階段: php buffer=》web server buffer=》browser buffer。 最後顯示到瀏覽器
預設情況下,php buffer 是開啟的,而且該 buffer 預設值是4096,即4 kb。你可以通過在php.ini配置檔案中找到output_buffering配置。buffer是一個記憶體地址空間,Linux系統預設大小一般為4096(4kb),即一個記憶體頁。主要用於儲存速度不同步的裝置或者優先順序不同的裝置之間傳辦理資料的區域。通過buffer,可以使程式這間的相互等待變少。這裡說一個通俗一點的例子,你開啟文字編輯器編輯一個檔案的時候,你每輸入一個字元,作業系統並不會立即把這個字元直接寫入到磁碟,而是先寫入到buffer,當寫滿了一個buffer的時候,才會把buffer中的資料寫入磁碟,當然當呼叫核心函式flush()的時候,強制要求把buffer中的髒資料寫回磁碟。
舉個例子
<?php echo "南無阿彌陀佛<br>"; header("content-type:text/html;charset='utf-8'"); echo "真善忍好!"; //output //南無阿彌陀佛 //真善忍好
header()必須在任何實際輸出之前呼叫,但是我們程式已經輸出了,卻正常執行。在看下面的程式碼:
<?php echo "南無阿彌陀佛<br>"; ob_flush(); header("content-type:text/html;charset='utf-8'"); echo "真善忍好!"; //output //南無阿彌陀佛 //Cannot modify header information - headers already sent by (output started at E:\php\test.php:3) //真善忍好
上面程式說明程式並沒有立即輸出,而當呼叫ob_flush 函式的時候才重新整理緩衝,輸出。
ob_flush() 與 flush()
ob_flush() , flush() 函式php 手冊上都有詳細的說明,你可以去查閱一下。二者的區別是:
ob_flush() 是重新整理PHP自身的緩衝區
flush()是 它是重新整理WebServer 伺服器的緩衝。輸出到瀏覽器。但是會出現下面的情況:
- 個別web伺服器程式,特別是Win32下的web伺服器程式,在傳送結果到瀏覽器之前,仍然會快取指令碼的輸出,直到程式結束為止。
- 有些Apache的模組,比如mod_gzip,可能自己進行輸出快取,這將導致flush()函式產生的結果不會立即被髮送到客戶端瀏覽器。
- 甚至瀏覽器也會在顯示之前,快取接收到的內容。例如 Netscape 瀏覽器會在接受到換行或 html 標記的開頭之前快取內容,並且在接受到 </table> 標記之前,不會顯示出整個表格。
- 一些版本的 Microsoft Internet Explorer 只有當接受到的256個位元組以後才開始顯示該頁面,所以必須傳送一些額外的空格來讓這些瀏覽器顯示頁面內容。
比如:
<?php /** Server:LightTPD/1.4.28 (Win32) X-Powered-By:PHP/5.3.27 */ echo '佛法無邊'."<BR>"; ob_flush(); flush(); sleep(1); echo '法輪常轉'; //output
上面的程式碼 在 chrome 瀏覽器上面 是一行一行的輸出,在ie系列的瀏覽器則是全部輸出。其實就是上面的 第四條一些瀏覽器只有當接收256個字元才開始顯示。把上面的程式碼改成下面形式:
<?php /** Server:LightTPD/1.4.28 (Win32) X-Powered-By:PHP/5.3.27 */ echo str_pad('',240)."\n"; echo '佛法無邊'."<BR>"; ob_flush(); flush(); sleep(1); echo '法輪常轉'; //output
這樣在ie下面就會一行一行輸出,因為超過256個字元。
ob 其他函式說明
1.ob_end_flush 與 ob_end_clean
end 的顧名思義就結束,關閉緩衝區,都是關閉輸出緩衝,一個是輸出緩衝區,一個是清除。比如
<?php /** Server:LightTPD/1.4.28 (Win32) X-Powered-By:PHP/5.3.27 */ echo 'before'; ob_end_clean(); echo str_pad('',4096)."\n"; for ($i=10; $i>0; $i--) { echo $i; sleep(1); }
上述程式碼是一下輸出全部內容,而不是一個一個輸出。ob_end_clean() 不是關閉了緩衝了?怎麼不是一個一個輸出呢,其實我們上面也說了,php 不是直接輸出給瀏覽器,而是 web server。 雖然php 沒有了 緩衝。但是web server 還是有的。所以下面程式碼:
/** Server:LightTPD/1.4.28 (Win32) X-Powered-By:PHP/5.3.27 */ echo 'before'; ob_end_clean(); echo str_pad('',4096)."\n"; for ($i=10; $i>0; $i--) { flush(); echo $i; sleep(1); }
加上flush(),就會一行一行輸出。 如果把ob_end_clean 換成 ob_end_flush 會把 before 輸出來。
其他函式 可參考手冊,比較簡單。
總結
php 指令碼到瀏覽器,要經過 php buffer=》web server buffer=》browser buffer。 最後顯示到瀏覽器。 缺一不可。 所以我們要 ob_flush 和 flush 以及加上 echo str_pad(”,4096) 才能除錯出你想要的效果。
相關文章
- PHP的輸出緩衝區PHP
- SAP SD基礎知識之輸出控制(Output Control)
- PHP 輸出緩衝區應用PHP
- 輸出緩衝
- 帶緩衝的輸入/輸入流
- HTML <output> 輸出域HTML
- SqlConnection,command基本用法,output,輸出SQL
- C語言清空輸入緩衝區C語言
- Java緩衝輸出位元組流BufferedOutputStreamJava
- 掌握CFML:在輸出緩衝區中高效搜尋字串的技巧字串
- cmu15545筆記-併發控制總結(Concurrency Control Summary)筆記
- 緩衝管理
- 為什麼關閉一個緩衝區輸出流之前應使用flush方法?
- [20190603]關於dbms_output輸出問題.txt
- [20211231]set linesize and dbms_output.line輸出問題.txt
- PHP-將變數輸出成 array 結構PHP變數
- JavaScript 緩衝運動JavaScript
- Java™ 教程(緩衝流)Java
- 無緩衝阻塞 chan
- Java NIO:緩衝區Java
- stdio流緩衝區
- 雙緩衝學習
- 緩衝位元組流#
- MySQL InnoDB緩衝池MySql
- 開關電源緩衝吸收電路:拓撲吸收、RC吸收、RCD吸收、鉗位吸收、無損吸收、LD緩衝、LR緩衝、飽和電感緩衝、濾波緩衝、振鈴_rc吸收和rcd吸收
- 演算法競賽中的常用輸入輸出總結演算法
- 輸入緩衝與土狼時間的討論與實現
- Golang併發程式設計有緩衝通道和無緩衝通道(channel)Golang程式設計
- [20201218]dbms_output.put_line無法輸出前面的空格.txt
- php nginx 實時輸出PHPNginx
- 演算法題 - ACM 模式中常用輸入輸出用法總結演算法ACM模式
- Linux 命令 管道 緩衝區Linux
- Java NIO 之緩衝區Java
- Go 緩衝通道(bufchan)用法Go
- Java整數緩衝區Java
- CSAPP緩衝實驗buflabAPP
- Unity深度緩衝區指令Unity
- 緩衝帶裡的少年
- 今日總結-結對作業衝刺