PHP中的Streams详细介绍_php实例

Streams 是PHP提供的一个强有力的工具,我们常常在不经意会使用到它,如果善加利用将大大提高PHP的生产力。 驾驭Streams的强大力量后,应用程序将提升到一个新的高度。

下面是PHP手册中对Streams的一段描述:

复制代码 代码如下:

Streams 是在PHP 4.3.0版本被引入的,它被用于统一文件、网络、数据压缩等类文件的操作方式,为这些类文件操作提供了一组通用的函数接口。简而言之,一个stream就是一个具有流式行为的资源对象。也就是说,我们可以用线性的方式来对stream进行读取和写入。并且可以用使用fseek()来跳转到stream内的任意位置。

每个Streams对象都有一个包装类,在包装中可以添加处理特殊协议和编码的相关代码。PHP中已经内置了一些常用的包装类,我们也可以创建和注册自定义的包装类。我们甚至能够使用现有的context和filter对包装类进行修改和增强。

Stream 基础知识

Stream 可以通过<scheme>://<target>方式来引用。其中<scheme>是包装类的名字,<target>中的内容是由包装类的语法指定,不同的包装类的语法会有所不同。

PHP默认的包装类是file://,也就是说我们在访问文件系统的时候,其实就是在使用一个stream。我们可以通过下面两种方式来读取文件中的内容,readfile(‘/path/to/somefile.txt')或者readfile(‘file:///path/to/somefile.txt'),这两种方式是等效的。如果你是使用readfile(‘http://google.com/'),那么PHP会选取HTTP stream包装类来进行操作。

正如上文所述,PHP提供了不少内建的包转类,protocol以及filter。 按照下文所述的方式,可以查询到本机所支持的包装类:

复制代码 代码如下:

<?php
print_r(stream_get_transports());
print_r(stream_get_wrappers());
print_r(stream_get_filters());

在我机器上的输出结果为:

复制代码 代码如下:

Array
(
    [0] => tcp
    [1] => udp
    [2] => unix
    [3] => udg
    [4] => ssl
    [5] => sslv3
    [6] => sslv2
    [7] => tls
)
Array
(
    [0] => https
    [1] => ftps
    [2] => compress.zlib
    [3] => compress.bzip2
    [4] => php
    [5] => file
    [6] => glob
    [7] => data
    [8] => http
    [9] => ftp
    [10] => zip
    [11] => phar
)
Array
(
    [0] => zlib.*
    [1] => bzip2.*
    [2] => convert.iconv.*
    [3] => string.rot13
    [4] => string.toupper
    [5] => string.tolower
    [6] => string.strip_tags
    [7] => convert.*
    [8] => consumed
    [9] => dechunk
    [10] => mcrypt.*
    [11] => mdecrypt.*
)

提供的功能非常多,看上去还不错吧?

除了上述内建的Stream,我们还可以为 Amazon S3, MS Excel, Google Storage, Dropbox 甚至Twitter编写更多的第三方的Stream。

php:// Streams包装类

PHP中内建了本语言用于处理I/O stream的包装类。可以分为几类,基础的有php://stdin,php://stdout, 以及php://stderr,这3个stream分别映射到默认 的I/O资源。同时PHP还提供了php://input,通过这个包装类可以使用只读的方式访问POST请求中的raw body。 这是一项非常有用的功能,特别是在处理那些将数据负载嵌入到POST请求中的远程服务时。

下面我们使用cURL工具来做一个简单的测试:

复制代码 代码如下:

curl -d "Hello World" -d "foo=bar&name=John" http://localhost/dev/streams/php_input.php

在PHP脚本中使用print_r($_POST)的测试结果如下所示:

复制代码 代码如下:

Array
(
    [foo] => bar
    [name] => John
)

我们注意$_POST array中是无法访问到第一项数据的。但是如果我们使用readfile(‘php://input'),结果就不同了:

复制代码 代码如下:

Hello World&foo=bar&name=John

PHP 5.1又增加了php://memory和php://tempstream这两个包转类,用于读写临时数据。正如包装类命名中所暗示的,这些数据被存储在底层系统中的内存或者临时文件中。

php://filter是一个元包装类,用于为stream增加filter功能。在使用readfile()或者file_get_contents()/stream_get_contents()打开stream时,filter将被使能。下面是一个例子:

复制代码 代码如下:

<?php
// Write encoded data
file_put_contents("php://filter/write=string.rot13/resource=file:///path/to/somefile.txt","Hello World");

// Read data and encode/decode
readfile("php://filter/read=string.toupper|string.rot13/resource=http://www.google.com");

在第一个例子中使用了一个filter来对保存到磁盘中的数据进行编码处理,在二个例子中,使用两个级联的filter来从远端的URL读取数据。使用filter能为你的应用带来极为强大的功能。

Stream上下文

context是一组stream相关的参数或选项,使用context可以修改或增强包装类的行为。例如使用context来修改HTTP包装器是一个常用到的使用场景。 这样我们就可以不使用cURL工具,就能完成一些简单的网络操作。下面是一个例子:

复制代码 代码如下:

<?php
$opts = array(
  'http'=>array(
    'method'=>"POST",
    'header'=> "Auth: SecretAuthTokenrn" .
        "Content-type: application/x-www-form-urlencodedrn" .
              "Content-length: " . strlen("Hello World"),
    'content' => 'Hello World'
  )
);
$default = stream_context_get_default($opts);
readfile('http://localhost/dev/streams/php_input.php');

首先要定义一个options array,这是个二位数组,可以通过$array['wrapper']['option_name']的形式来访问其中的参数。(注意每个包装类中context的options是不同的)。然后调用stream_context_get_default()来设置这些option,stream_context_get_default()同时还会将默认的context作为结果返回回来。设置完成后,接下来调用readfile(),就会应用刚才设置好的context来抓取内容。

在上面的例子中,内容被嵌入到request的body中,这样远端的脚本就可以使用php://input来读取这些内容。同时,我们还能使用apache_request_headers()来获取request的header,如下所示:

复制代码 代码如下:

Array
(
    [Host] => localhost
    [Auth] => SecretAuthToken
    [Content-type] => application/x-www-form-urlencoded
    [Content-length] => 11
)

在上面的例子中是修改默认context的参数,当然我们也可以创建一个新的context,进行交替使用。

复制代码 代码如下:

<?php
$alternative = stream_context_create($other_opts);
readfile('http://localhost/dev/streams/php_input.php', false, $alternative);

Streams结论

我们怎样在现实世界中驾驭stream的强大力量呢?使用stream能为我们的程序带来什么现实的好处? 正如前文介绍的那样,stream对所有文件系统相关的功能进行了抽象,所以我第一个想到的应用场景是使用虚拟文件系统的包装类来访问PaaS供应商提供的服务,比如说访问HeroKu或者AppFog,它们实际上都没有真正文件系统。 使用stream只要对我们的应用程序稍作修改,就可以将其移植到云端。 接下来–在我的下一篇文章中–我将介绍如何编写自定义的包装类以实现对特殊文件格式和编码格式的操作。

时间: 2024-09-23 22:36:34

PHP中的Streams详细介绍_php实例的相关文章

基于php设计模式中工厂模式详细介绍_php实例

工厂模式:由工厂类根据参数来决定创建出哪一种产片类的实例工厂类:一个专门用来创建其他对象的方法类.即按需分配,传入参数进行选择,返回具体的类作用:对象创建的封装.简化创建对象的操作,即调用工厂类的一个方法来得到需要的类补充:1.主要角色:抽象产品(Product).具体产品(Concrete Product).抽象工厂角色(Creator)2.优缺点    优点:工厂方法模式可以允许系统在不修改工厂角色的情况下引进心产品    缺点:客户可能仅仅为了创建一个特定的Concrete Product

Yii2增删改查之查询 where参数详细介绍_php实例

概述 由于官方手册关于where的介绍比较少,所以想自己整理一下,以便大家的学习和自己回头查询.本篇文章会详细介绍and.or.between.in.like在where方法中的使用方法和举例. and // 我们要查询id大于1并且小于3的数据 $userInfo = User::find()->where(['and' , 'id > 1' , 'id < 3'])->all(); // 或者用以下方式,更为安全 $userInfo = User::find()->whe

php中is_null,empty,isset,unset 的区别详细介绍_php实例

is_null, empty, isset, unset 我们先来看看这4个函数的描述. isset 判断变量是否已存在(配置)unset 把变量删除(释放)掉empty 判断变量是否为空is_null 判断变量是否为NULLok,已经开始搞人了.那么开始,这4个函数中除了unset,其他3个都是判断函数,unset首先出局,因为他不会搞错,其次是is_null,我们可以把它看成是!isset,是isset的一个逆操作,下面一张表可以很清楚的说明他们之间的关系: 复制代码 代码如下: 变量   

php中引用符号(&amp;)的使用详细介绍_php实例

与C语言中的指针是有差别的.C语言中的指针里面存储的是变量的内容在内存中存放的地址变量的引用. PHP 的引用允许你用两个变量来指向同一个内容 $a="ABC"; $b =&$a; echo $a;//这里输出:ABC echo $b;//这里输出:ABC $b="EFG"; echo $a;//这里$a的值变为EFG 所以输出EFG echo $b;//这里输出EFG 函数的传址调用 传址调用我就不多说了 下面直接给出代码 <?php functio

php中get_headers函数的作用及用法的详细介绍_php实例

get_headers() 是PHP系统级函数,他返回一个包含有服务器响应一个 HTTP 请求所发送的标头的数组.如果失败则返回 FALSE 并发出一条 E_WARNING 级别的错误信息(可用来判断远程文件是否存在). 函数定义 array get_headers ( string $url [, int $format = 0 ] ) 参数 url 目标 URL format 如果将可选的 format 参数设为 1,则 get_headers() 会解析相应的信息并设定数组的键名. 示例

PHP字符串的编码问题的详细介绍_php实例

      大家都知道,不同字符编码,其在内存占用的字节数不一样.如ASCII编码字符占用1个字节,UTF-8编码的中文字符是3字节,GBK为2个字节.       PHP 也自带几种字符串截取函数,其中常用到的就是 substr 和 mb_substr.     使用substr截取中文字符时会出现乱码,这是因为substr是按字节来截取的.即UTF-8编码的中文,使用substr截取,只会截取1/3个中文,当然出现乱码了.     mb_substr ( string $str , int

php arsort 数组降序排序详细介绍_php实例

arsort 对数组进行降序排序并保持索引关系. 基本语法 bool arsort ( array &$array [, int $sort_flags = SORT_REGULAR ] ) 本函数对数组进行降序排序,数组的索引保持和单元的关联. arsort函数主要用于对那些单元顺序很重要的结合数组进行排序. 参数介绍: 参数 描述 array 必需.输入的数组. sort_flags 可选.规定如何排列数组的元素/项目.可能的值: 0 = SORT_REGULAR - 默认.把每一项按常规顺

AngularJS中的Promise详细介绍及实例代码_AngularJS

Angular中的Promise 在用jQuery的时候就知道 promise 是 Js异步编程模式的一种模式,但是不是很明白他跟JQuery的deferred对象有什么区别.随着公司项目的进行,要跟后台接数据了,所以决定搞定它. Promise Promise是一种模式,以同步操作的流程形式来操作异步事件,避免了层层嵌套,可以链式操作异步事件. 我们知道,在编写JavaScript异步代码时,callback是最最简单的机制,可是用这种机制的话必须牺牲控制流.异常处理和函数语义化为代价,甚至会

基于MySQL分区性能的详细介绍_php实例

一,      分区概念  分区允许根据指定的规则,跨文件系统分配单个表的多个部分.表的不同部分在不同的位置被存储为单独的表.MySQL从5.1.3开始支持Partition. 分区和手动分表对比 手动分表  分区 多张数据表 一张数据表 重复数据的风险 没有数据重复的风险 写入多张表 写入一张表 没有统一的约束限制 强制的约束限制   MySQL支持RANGE,LIST,HASH,KEY分区类型,其中以RANGE最为常用: Range(范围)–这种模式允许将数据划分不同范围.例如可以将一个表通