和SPL一样,在PHP手册里面,流被划为“other basic extensions”里面,是PHP开发中一个容易被忽视的函数系列。但其实在C++/Java中,流是一个很重要的概念。流的概念源于UNIX中的管道,管道是一条不间断的字节流,用来实现程序和进程间通信,或者读写外设,外部文件等。
流的概念是在php 4.3.0中被引入的。我们知道,文件操作,网络操作,数据压缩操作等具有一定的共性,比如线性的读/写或者随机定位,流就是用来把这些操作抽象出一个统一的接口以供开发者们使用,因此“流”被定义为a resource object which exhibits streamable behavior。
当然,我们可以对stream进行进一步的封装(wrapper),这样就可以handle一些特定的协议。例如http wrapper可以把一个url翻译成对远程服务器上文件的HTTP/1.0请求。PHP默认已经实现了很多wrappers,可以用过stream_get_wrappers()来得到这个列表
stream wrapper的好处是使得开发者使用统一的接口来打开一个像URL,FTP之类的连接,而不需要关心协议的内容,除非自己实现一个php wrapper。
当然,除了这些内置的php stream wrappers以外,我们可以增加自定义的流,添加的方式有两种
- 通过php脚本stream_wrapper_register()来实现
- 通过调用php stream API来编写C扩展实现。
流的使用方式为scheme://target,其中 scheme为wrapper的名称(例如http),target取决于一个具体的stream.
那么php stream到底有哪些应用场景呢?
task: 将一个用BZ2格式压缩的文件,将其编码格式从ISO-8859-1转至UTF-8,将全文转成大写,然后进行ROT-13编码,再写入一个新的文件。
如果对php stream有简要的了解以后,这个任务会非常容易
<?php
/**
* Example of stream filtering.
*/
// Open two file handles.
$in = fopen(‘test.txt.bz2‘, ‘rb‘);
$out = fopen(‘test-uppercase.txt‘, ‘wb‘);
// Add a decode filter to the first.
stream_filter_prepend($in, ‘bzip2.decompress‘, STREAM_FILTER_READ);
// Change the charset from ISO-8859-1 to UTF-8
stream_filter_append($out, ‘convert.iconv.ISO-8859-1/UTF-8‘, STREAM_FILTER_WRITE);
// Uppercase the entire string.
stream_filter_append($out, ‘string.toupper‘, STREAM_FILTER_WRITE);
// Run ROT-13 on the output.
stream_filter_append($out, ‘string.rot13‘, STREAM_FILTER_WRITE);
// Now copy. All of the filters are applied here.
stream_copy_to_stream($in, $out);
// Clean up.
fclose($in);
fclose($out);
?>
这是因为php stream中一个特性-filter,其可以对流按照想要的方式进行过滤。php有一些内置的过滤器,可以通过stream_get_filters()来查看
当然,stream wrapper也提供了API让开发者自己开发一些filter。