php的各种IO流以及用法

PHP的各种I/O流以及用法

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模式)

1
2
3
4
5
6
7
8
9
10
11
<?php
/**
* Created by PhpStorm.
* User: xuanyi
* Date: 2018/12/10
* Time: 22:00
*/
echo "请输入你的名字:\n";
$stdin = fopen('php://stdin', 'r');
$data = fgets($stdin);
echo "{$data}你好啊!";

res
res

可以看到,上面使用了 php://stdin 协议,打开了一个标准输入的操作句柄,然后可以读取用户在控制台输入的数据。上面的代码也可以写成:

1
2
3
4
5
6
7
8
9
10
<?php
/**
* Created by PhpStorm.
* User: xuanyi
* Date: 2018/12/10
* Time: 22:00
*/
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 模式运行)

1
2
3
4
5
6
7
8
9
10
11
<?php
/**
* Created by PhpStorm.
* User: xuanyi
* Date: 2018/12/11
* Time: 9:44
*/
$stdout = fopen('php://stdout', 'w');
fwrite($stdout, "这是输出1\n");
echo "这是输出2\n";
fwrite(STDOUT, "这是输出3\n");

res

和 stdin 注意点一样,这里就不复制了,但需要加上一条:

在 php-cli 模式下,作用和 echo 相同,但是实现方式不一样

STDERR 标准错误

STDERR 标准错误和 STDOUT 差不多,都是将字符串默认打印到控制台(可使用freopen 重定向到文件),但是这个是打印错误用的,区分就是 STDERR 会将打印的字符串变成红色(需要终端支持)。例如:(注意,使用 php-cli 模式运行)

1
2
3
4
5
6
7
8
9
10
11
12
<?php
/**
* Created by PhpStorm.
* User: xuanyi
* Date: 2018/12/11
* Time: 10:01
*/
$stderr = fopen('php://stderr', 'w');
fwrite($stderr, "这是输出1\n");
echo "这是输出2\n";
fwrite(STDERR, "这是输出3\n");
$a = $b;

res

从上面的 STDOUT 注意点到这里可以发现,STDERR 和 echo 语句的输出顺序是不相同的,个人猜测是 echo 的缓冲区和 STDERR 不相同。

php://input

从这里开始,就和上面的3个程序标准I/O流关系不打了,咱们继续往下看,该部分参考:http://www.nowamagic.net/academy/detail/12220520,有时间可详细阅读,本文只做功能简单介绍。
php://input 是个可以访问请求的原始数据的只读流。
通俗来讲:php://input 可接收用户请求过来的原始数据流(大多数时候作用于 POST 请求),例如:(需要使用 web 方式请求)

服务端代码:

1
2
3
4
5
6
7
<?php
$data = file_get_contents("php://input", 'r');
echo "下面是php://input\n";
var_dump($data);
echo 1;
echo "下面是 POST:\n";
var_dump($_POST);

客户端请求代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
<?php
/**
* Created by PhpStorm.
* User: xuanyi
* Date: 2018/12/11
* Time: 10:27
*/
/**
* @param $url
* @param $post_data
*/
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' => 'xuanyi',
'password' => '123456'
);
$data = send_post('http://test.com', $post_data);
var_dump($data);

输出:
res

php://output

php://output 是一个只写的数据流,允许你以 print 和 echo 一样的方式写入到输出缓冲区。可以说功能和 echo 一样(可以在 web 和 php-cli 使用)

1
2
<?php
file_put_contents('php://output', '小灰灰最棒');

res
res

php://fd

php://fd 允许直接访问指定的文件描述符。例如:php://fd/3 引用了文件描述符3。用法:在 linux 中,一切皆文件,当启动系统时,先会启动STDIN 标准输入(文件描述符 0),之后是 STDOUT 文件描述符1,STDERR 文件描述符2。

使用 php://fd,可直接调用该文件:

1
2
3
4
5
6
<?php
$stdin = fopen('php://input', 'r');
$data = fgets($stdin);
echo "这是STDIN输入的:{$data}\n";
file_put_contents('php://fd/2', "这是STDERR\n");
file_put_contents('php://fd/1', "这是STDOUT\n");

输出:
res

php://memory 和 php://temp

php://memory 和 php://temp 是一个类似文件包装器的数据流,允许读写临时数据。两者的唯一区别是 php://memory 总是把数据储存到内存中,而 php://temp 会在内存量达到预定义的限制后(默认是2MB)存入临时文件中。临时文件位置的决定和 sys_get_temp_dir() 的方式一致。php://temp 的内存限制可通过添加 /maxmemory:NN 来控制,NN 是以字节为单位、保留在内存的最大数据量,超过则使用临时文件。例如:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
<?php
// set the limit to 5 MB
$fiveMBs = 5 * 1024 * 1024;
// maxmemory 可以调整存储空间大小
$temp_f = fopen("php://temp/maxmemory:{$fileMBs}", 'r+');
fputs($temp_f, "hello,小灰灰,我是temp的数据\n");
// 由于写入数据时,指针已经到了末尾,需要重置指针才能读取到数据
rewind($temp_f);
echo stream_get_contents($temp_f);

$fileMBs = 5 * 1024 * 1024;
// maxemory 可以调整存储空间大小
$memory_f = fopen("php://memory", 'r+');
fputs($memory_f, "hello,小灰灰,我是memory的数据\n\n");
// 由于写入数据时,指着已经到了末尾,需要重置指定才能读取到数据
rewind($memory_f);
echo stream_get_contents($memory_f);

res
注意:关闭文件之后数据将无法获取

php://filter

php://filter 是一种元封装器,设计用于数据流打开时的筛选过滤应用。这对于一体式(all-in-one)的文件函数非常有用,类似 readfile()、file() 和 file_get_contents(),在数据流内容读取之前没有机会应用其他过滤器。

php://filter 目标使用以下的参数作为它路径的一部分。复合过滤链能够在一个路径上指定。详细使用这些参数可以参考具体范例。

php://filter 参数:
res

可选项:
封装协议摘要(针对 php://filter,参考被筛选的封装器。)
res

该协议个人不是很会用,并且个人觉得没啥必要学习,所以直接复制php手册的例子吧

1
2
3
4
5
6
<?php
/* 这会以大写字母输出 www.example.com 的全部内容 */
readfile("php://filter/read=string.toupper/resource=http://www.example.com");

/* 这会和以上所做的一样,但还会用 ROT13 的加密。 */
readfile("php://filter/reda=string.toupper|string.rot13/resource=http://www.example.com");

本文为转载文章,来自仙士可博客www.php20.cn

文章目录
  1. 1. PHP的各种I/O流以及用法
    1. 1.1. php://协议
    2. 1.2. STDIN 输入流
    3. 1.3. STDOUT 输出流
    4. 1.4. STDERR 标准错误
    5. 1.5. php://input
    6. 1.6. php://output
    7. 1.7. php://fd
    8. 1.8. php://memory 和 php://temp
    9. 1.9. php://filter
本站总访问量 | 本页面被访问 | 您是第位小伙伴

© XueSi博客 版权所有 备案号 : 赣ICP备19008485号-1