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调用三种数据库的方法(3)
Oct 09 PHP
如何实现给定日期的若干天以后的日期
Oct 09 PHP
用ODBC的分页显示
Oct 09 PHP
php实现单链表的实例代码
Mar 22 PHP
php中filter函数验证、过滤用户输入的数据
Jan 13 PHP
php计算给定时间之前的函数用法实例
Apr 03 PHP
php通过获取头信息判断图片类型的方法
Jun 26 PHP
PHP实现简单实用的分页类代码
Apr 08 PHP
php实现留言板功能
Mar 05 PHP
php实现批量上传数据到数据库(.csv格式)的案例
Jun 18 PHP
PHP使用正则表达式实现过滤非法字符串功能示例
Jun 04 PHP
PHP 范围解析操作符(::)用法分析【访问静态成员和类常量】
Apr 14 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 强制下载文件实现代码
2013/10/28 PHP
php session_start()出错原因分析及解决方法
2013/10/28 PHP
php中autoload的用法总结
2013/11/08 PHP
PHP echo,print,printf,sprintf函数之间的区别与用法详解
2013/11/27 PHP
php计算整个目录大小的方法
2015/06/01 PHP
WordPress开发中用于标题显示的相关函数使用解析
2016/01/07 PHP
简单的pgsql pdo php操作类实现代码
2016/08/25 PHP
php操作access数据库的方法详解
2017/02/22 PHP
实例化php类时传参的方法分析
2020/06/05 PHP
PHP常量DIRECTORY_SEPARATOR原理及用法解析
2020/11/10 PHP
Javascript 读后台cookie代码
2008/09/15 Javascript
javascript delete 使用示例代码
2010/03/29 Javascript
一个简单的瀑布流效果(主体形式自写)
2013/05/27 Javascript
angularjs的一些优化小技巧
2014/12/06 Javascript
jQuery实现在textarea指定位置插入字符或表情的方法
2015/03/11 Javascript
jQuery实现指定内容滚动同时左侧或其它地方不滚动的方法
2015/08/08 Javascript
js正则表达式验证密码强度【推荐】
2017/03/03 Javascript
jQuery扇形定时器插件pietimer使用方法详解
2017/07/18 jQuery
Vue生命周期activated之返回上一页不重新请求数据操作
2020/07/26 Javascript
ant design vue中表格指定格式渲染方式
2020/10/28 Javascript
python安装mysql-python简明笔记(ubuntu环境)
2016/06/25 Python
详解python路径拼接os.path.join()函数的用法
2019/10/09 Python
pandas 空数据处理方法详解
2019/11/02 Python
Python中zip()函数的解释和可视化(实例详解)
2020/02/16 Python
Omio中国:全欧洲低价大巴、火车和航班搜索和比价
2018/08/09 全球购物
神话般的珠宝:Ross-Simons
2020/07/13 全球购物
家长写给老师的建议书
2014/03/13 职场文书
大学生职业生涯十年规划书范文
2014/09/17 职场文书
自愿离婚协议书范文2014
2014/10/12 职场文书
2014年工程工作总结
2014/11/25 职场文书
技术股东合作协议书
2014/12/02 职场文书
2015年度服装销售工作总结
2015/03/31 职场文书
关于教师节的广播稿
2015/08/19 职场文书
JavaScript 防篡改对象的用法示例
2021/04/24 Javascript
springboot使用Redis作缓存使用入门教程
2021/07/25 Redis
VUE中的v-if与v-show区别介绍
2022/03/13 Vue.js