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抽象类 介绍
Jun 13 PHP
通过PHP的内置函数,通过DES算法对数据加密和解密
Jun 21 PHP
ThinkPHP模板判断输出Present标签用法详解
Jun 30 PHP
destoon切换城市后实现logo旁边显示地区名称的方法
Aug 21 PHP
phpstorm编辑器乱码问题解决
Dec 01 PHP
php 5.6版本中编写一个PHP扩展的简单示例
Jan 20 PHP
php判断输入是否是纯数字,英文,汉字的方法
Mar 05 PHP
php操作redis缓存方法分享
Jun 03 PHP
php判断手机浏览还是web浏览,并执行相应的动作简单实例
Jul 28 PHP
基于thinkPHP框架实现留言板的方法
Oct 17 PHP
php实现的二分查找算法示例
Jun 20 PHP
PHP实现普通hash分布式算法简单示例
Aug 06 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
对盗链说再见...
2006/10/09 PHP
桌面中心(二)数据库写入
2006/10/09 PHP
php获取一定范围内取N个不重复的随机数
2016/05/28 PHP
浅谈PHP接入(第三方登录)QQ登录 OAuth2.0 过程中遇到的坑
2017/10/13 PHP
PHP设计模式之简单工厂和工厂模式实例分析
2019/03/25 PHP
5个javascript的数字格式化函数分享
2011/12/07 Javascript
JavaScript访问CSS属性的几种方式介绍
2014/07/21 Javascript
JavaScript焦点事件、鼠标事件和滚轮事件使用详解
2016/01/15 Javascript
图片懒加载插件实例分享(含解析)
2017/01/09 Javascript
angular或者js怎么确定选中ul中的哪几个li
2017/08/16 Javascript
深入理解Vue Computed计算属性原理
2018/05/29 Javascript
JavaScript实现邮箱后缀提示功能的示例代码
2018/12/13 Javascript
[jQuery] 事件和动画详解
2019/03/05 jQuery
Nodejs实现用户注册功能
2019/04/14 NodeJs
在vue项目中使用codemirror插件实现代码编辑器功能
2019/08/27 Javascript
[01:53]3.19 DOTA2发布会 现场精彩Coser表演
2014/03/25 DOTA
[01:05:40]VG vs Newbee 2018国际邀请赛小组赛BO2 第二场 8.17
2018/08/20 DOTA
python迭代器的使用方法实例
2013/11/21 Python
详解Python中的strftime()方法的使用
2015/05/22 Python
python递归删除指定目录及其所有内容的方法
2017/01/13 Python
python3学习之Splash的安装与实例教程
2018/07/09 Python
wtfPython—Python中一组有趣微妙的代码【收藏】
2018/08/31 Python
python矩阵/字典实现最短路径算法
2019/01/17 Python
pyqt远程批量执行Linux命令程序的方法
2019/02/14 Python
Pytorch 搭建分类回归神经网络并用GPU进行加速的例子
2020/01/09 Python
Python中正则表达式对单个字符,多个字符和匹配边界等使用
2021/01/27 Python
椰子猫砂:CatSpot
2018/08/27 全球购物
德国受欢迎的旅游和休闲网站:lastminute.de
2019/09/23 全球购物
美容院考勤制度
2014/01/30 职场文书
幼儿园毕业教师感言
2014/02/21 职场文书
英语系本科生求职信
2014/07/15 职场文书
群众路线教育实践活动心得体会(四风)
2014/11/03 职场文书
导游词之永泰公主墓
2019/12/04 职场文书
浅谈node.js中间件有哪些类型
2021/04/29 Javascript
利用Java设置Word文本框中的文字旋转方向的实现方法
2021/06/28 Java/Android
解决Laravel使用验证时跳转到首页的问题
2021/11/17 PHP