分析php://output和php://stdout的区别
PHP包含了以php://开头的一系列输出输出流,如php://stdin,php://stdout等。今天查看代码时,忽然想到一个问题:php://output和php://stdout有什么区别?
从PHP的官方文献中找答案,对输入流php://stdin和php://input的解释分别如下(输出流的解释过于简略):
php://stdin
php://stdin,php://stdoutandphp://stderrallowdirectaccesstothecorrespondinginputoroutputstreamofthePHPprocess.Thestreamreferencesaduplicatefiledescriptor,soifyouopenphp://stdinandlatercloseit,youcloseonlyyourcopyofthedescriptor-theactualstreamreferencedbySTDINisunaffected.NotethatPHPexhibitedbuggybehaviorinthisregarduntilPHP5.2.1.ItisrecommendedthatyousimplyusetheconstantsSTDIN,STDOUTandSTDERRinsteadofmanuallyopeningstreamsusingthesewrappers.
php://stdinisread-only,whereasphp://stdoutandphp://stderrarewrite-only.
php://input
php://inputisaread-onlystreamthatallowsyoutoreadrawdatafromtherequestbody.InthecaseofPOSTrequests,itispreferabletousephp://inputinsteadof$HTTP_RAW_POST_DATAasitdoesnotdependonspecialphp.inidirectives.Moreover,forthosecaseswhere$HTTP_RAW_POST_DATAisnotpopulatedbydefault,itisapotentiallylessmemoryintensivealternativetoactivatingalways_populate_raw_post_data.php://inputisnotavailablewithenctype=”multipart/form-data”.
文档并未直接阐述两者的区别,仔细对比可得出以下信息:1.均是只读流;2.php://stdin是PHP进程的标准输入,php://input用来读取请求正文的原始数据。通过这些信息,该如何正确认识两者的本质区别?
顺着php://stdin进程输入的提示,联想PHP进程的执行过程,再结合SAPI的差异,可以得到两者主要区别:php://stdin是PHP进程的输入流,执行生命周期内均可能有数据流入(例如CLI下的交互式输入);php://input是PHP执行时的外部输入流,一般数据只能读一次(具体看SAPI的实现)。同理可得到php://stdout和php://output的区别:php://stdout是PHP进程的标准输出流,php://output是返回的结果数据流。
下面用代码验证结论:
//file:test.php file_put_contents("php://output","messagesentbyoutput".PHP_EOL); file_put_contents("php://stdout","messagesentbystdout".PHP_EOL); print("messagesentbyprint".PHP_EOL); echo"SAPI:",PHP_SAPI,PHP_EOL;
命令行执行文件,输出如下:
messagesentbyoutput messagesentbystdout messagesentbyprint SAPI:cli
浏览器端请求,输出如下:
messagesentbyoutput messagesentbyprint SAPI:fpm-fcgi
在命令行下,PHP进程的标准输出流和结果输出流均指向终端,所有消息都打印出来。在浏览器端,PHP进程的输出流被忽略,只有结果数据流被发送到web服务器。同时,print和echo调用的信息都作为执行结果发往结果输出流,所以都正常显示。
最后再感慨一下PHP内置函数的简洁实用,一个file_put_contents函数就搞定流写入操作,换Java需要stream/writer一堆代码,也省去C风格的fopen/fwrite/fclose的繁琐。