PHP中的gzcompress、gzdeflate、gzencode函数详解


Posted in PHP onJuly 29, 2014

PHP中存在一组看起来很像的压缩解压函数:

压缩函数:gzcompress gzdeflate gzencode

解压函数:gzuncompress gzinflate gzdecode

gzdecode是PHP 5.4.0之后才加入的,使用的时候要注意兼容性问题。

这几个函数都以gz开头,让人想到gzip压缩,而光看函数名却又看不出它们之间的区别,只能查文档。

gzcompress gzdeflate gzencode函数的区别在于它们压缩的数据格式不同:

gzcompress使用的是ZLIB格式;

gzdeflate使用的是纯粹的DEFLATE格式;

gzencode使用的是GZIP格式;

但是有一点是相同的,它们压缩数据时都使用了DEFLATE压缩算法(理论上ZLIB和GZIP格式可以使用其他的压缩算法,但是目前实践中只使用DEFLATE算法),ZLIB和GZIP只不过是在DEFLATE的基础之上加了一些头部和尾部而已。

顺便提一下,HTTP协议中的Content-Encoding: deflate使用的是ZLIB格式而不是纯DEFLATE格式。

从PHP 5.4.0开始,gzcompress和gzdeflate函数加入了第三个参数$encoding,可以是三个常量:

ZLIB_ENCODING_RAW 对应于纯DEFLATE格式;

ZLIB_ENCODING_GZIP 对应于GZIP格式;

ZLIB_ENCODING_DEFLATE 对应于ZLIB格式(注意不是纯DEFLATE格式);

虽然文档没有提及,但是这三个常量也可以用在gzencode函数的第三个参数$encoding_mode中。

其实从PHP 5.4.0开始,这三个函数是一样的,只不过第三个参数的默认值不同;如果调用时传入第三个参数,那么这三个函数返回的数据相同。可以写一个简单的脚本测试:

<?php

$url = 'http://3water.com';

$s1 = gzdeflate($url, 1);

$s2 = gzencode($url, 1, ZLIB_ENCODING_RAW);

if (strcmp($s1, $s2) == 0) echo 'the same';

?>

运行可以看到$s1和$s2是相同的,为什么会这样呢?可以从PHP源码中找到答案,打开php-5.5.4\ext\zip\zlib.c,可以找到这样的代码:

#define PHP_ZLIB_ENCODE_FUNC(name, default_encoding) \

static PHP_FUNCTION(name) \

{ \

    char *in_buf, *out_buf; \

    int in_len; \

    size_t out_len; \

    long level = -1; \

    long encoding = default_encoding; \

    if (default_encoding) { \

        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s|ll", &in_buf, &in_len, &level, &encoding)) { \

            return; \

        } \

    } else { \

        if (SUCCESS != zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "sl|l", &in_buf, &in_len, &encoding, &level)) { \

            return; \

        } \

    } \

    if (level < -1 || level > 9) { \

        php_error_docref(NULL TSRMLS_CC, E_WARNING, "compression level (%ld) must be within -1..9", level); \

        RETURN_FALSE; \

    } \

    switch (encoding) { \

        case PHP_ZLIB_ENCODING_RAW: \

        case PHP_ZLIB_ENCODING_GZIP: \

        case PHP_ZLIB_ENCODING_DEFLATE: \

            break; \

        default: \

            php_error_docref(NULL TSRMLS_CC, E_WARNING, "encoding mode must be either ZLIB_ENCODING_RAW, ZLIB_ENCODING_GZIP or ZLIB_ENCODING_DEFLATE"); \

            RETURN_FALSE; \

    } \

    if (SUCCESS != php_zlib_encode(in_buf, in_len, &out_buf, &out_len, encoding, level TSRMLS_CC)) { \

        RETURN_FALSE; \

    } \

    RETURN_STRINGL(out_buf, out_len, 0); \

}


/* NOTE: The naming of these userland functions was quite unlucky */

/* {{{ proto binary gzdeflate(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_RAW])

   Encode data with the raw deflate encoding */

PHP_ZLIB_ENCODE_FUNC(gzdeflate, PHP_ZLIB_ENCODING_RAW);

/* }}} */
/* {{{ proto binary gzencode(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_GZIP])

   Encode data with the gzip encoding */

PHP_ZLIB_ENCODE_FUNC(gzencode, PHP_ZLIB_ENCODING_GZIP);

/* }}} */
/* {{{ proto binary gzcompress(binary data[, int level = -1[, int encoding = ZLIB_ENCODING_DEFLATE])

   Encode data with the zlib encoding */

PHP_ZLIB_ENCODE_FUNC(gzcompress, PHP_ZLIB_ENCODING_DEFLATE);

/* }}} */

可以看到,gzdeflate gzencode gzcompress三个函数都是用相同的PHP_ZLIB_ENCODE_FUNC宏定义的(是不是有些泛型的意味?),所以它们当然是相同的。

代码中的注释也承认这几个函数的名字起得不好,至于为什么会用这样的名字就不得而知了。

PHP 相关文章推荐
PHP学习之PHP表达式
Oct 09 PHP
PHP 编程的 5个良好习惯
Feb 20 PHP
PHP操作xml代码
Jun 17 PHP
几款免费开源的不用数据库的php的cms
Dec 19 PHP
一个图片地址分解程序(用于PHP小偷程序)
Aug 23 PHP
php中mysql操作buffer用法详解
Mar 19 PHP
php使用cookie实现记住用户名和密码实现代码
Apr 27 PHP
php文件操作小结(删除指定文件/获取文件夹下的文件名/读取文件夹下图片名)
May 09 PHP
PHP二维数组去重算法
Dec 17 PHP
php curl 模拟登录并获取数据实例详解
Dec 22 PHP
ThinkPHP3.2框架操作Redis的方法分析
May 05 PHP
PHP 使用位运算实现四则运算的代码
Mar 09 PHP
VB中的RasEnumConnections函数返回632错误解决方法
Jul 29 #PHP
php中的curl_multi系列函数使用例子
Jul 29 #PHP
PHP使用CURL_MULTI实现多线程采集的例子
Jul 29 #PHP
PHP实现把文本中的URL转换为链接的auolink()函数分享
Jul 29 #PHP
PHP自带函数给数字或字符串自动补齐位数
Jul 29 #PHP
Win2003+apache+PHP+SqlServer2008 配置生产环境
Jul 29 #PHP
php实现读取超大文件的方法
Jul 28 #PHP
You might like
php实现文件下载实例分享
2014/06/02 PHP
php上传文件常见问题总结
2015/02/03 PHP
PHP实现创建一个RPC服务操作示例
2020/02/23 PHP
使用jQuery+HttpHandler+xml模拟一个三级联动的例子
2011/08/09 Javascript
用Jquery.load载入页面实现局部刷新
2014/01/22 Javascript
jQuery使用before()和after()在元素前后添加内容的方法
2015/03/26 Javascript
JavaScript获取数组最小值和最大值的方法
2015/06/09 Javascript
javascript实现下雪效果【实例代码】
2016/05/03 Javascript
JQuery的attr 与 val区别
2016/06/12 Javascript
Bootstrap简单表单显示学习笔记
2016/11/15 Javascript
javascript 组合按键事件监听实现代码
2017/02/21 Javascript
vue router路由嵌套不显示问题的解决方法
2017/06/17 Javascript
Angular 5.x 学习笔记之Router(路由)应用
2018/04/08 Javascript
Vue项目History模式404问题解决方法
2018/10/31 Javascript
记一次vue-webpack项目优化实践详解
2019/02/17 Javascript
jQuery Ajax async=&gt;false异步改为同步时,解决导致浏览器假死的问题
2019/07/22 jQuery
JS原型prototype和__proto__用法实例分析
2020/03/14 Javascript
[06:35]2014DOTA2国际邀请赛 老男孩梦圆西雅图中国军团世界最强
2014/07/22 DOTA
浅析Python多线程下的变量问题
2015/04/28 Python
python在Windows下安装setuptools(easy_install工具)步骤详解
2016/07/01 Python
python+requests+unittest API接口测试实例(详解)
2017/06/10 Python
如何利用python查找电脑文件
2018/04/27 Python
python实现从文件中读取数据并绘制成 x y 轴图形的方法
2018/10/14 Python
Python从函数参数类型引出元组实例分析
2019/05/28 Python
Django框架创建项目的方法入门教程
2019/11/04 Python
使用Python实现批量ping操作方法
2020/05/06 Python
Python3爬虫RedisDump的安装步骤
2021/02/20 Python
老板电器官方购物商城:老板油烟机、燃气灶、消毒柜、电烤箱
2018/05/30 全球购物
咖啡店自主创业商业计划书
2014/01/22 职场文书
法制宣传月活动方案
2014/05/11 职场文书
党委班子对照检查材料
2014/08/19 职场文书
合伙开公司协议书范本
2014/10/28 职场文书
中学生社会实践教育活动总结
2015/05/06 职场文书
祝寿主持词
2015/07/02 职场文书
校园歌手大赛主持词
2015/07/03 职场文书
文艺有韵味的诗句(生命类、亲情类...)
2019/07/11 职场文书