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 利用Mail_MimeDecode类提取邮件信息示例
Jan 26 PHP
ThinkPHP模板判断输出Defined标签用法详解
Jun 30 PHP
php创建和删除目录函数介绍和递归删除目录函数分享
Nov 18 PHP
php猴子选大王问题解决方法
May 12 PHP
深入浅出php socket编程
May 13 PHP
Yii2主题(Theme)用法详解
Jul 23 PHP
php实现图片按比例截取的方法
Feb 06 PHP
PHP树形结构tree类用法示例
Feb 01 PHP
thinkPHP5框架接口写法简单示例
Aug 05 PHP
php+js实现的无刷新下载文件功能示例
Aug 23 PHP
PHP命名空间与自动加载机制的基础介绍
Aug 25 PHP
PHP实现常用排序算法的方法
Feb 05 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
Yii的Srbac插件用法详解
2016/07/14 PHP
thinkphp框架page类与bootstrap分页(美化)
2017/06/25 PHP
PDO::getAvailableDrivers讲解
2019/01/28 PHP
PHP+Ajax简单get验证操作示例
2019/03/02 PHP
极酷的javascirpt,让你随意编辑任何网页
2007/02/25 Javascript
28个JS验证函数收集
2010/03/02 Javascript
使用jQuery异步加载 JavaScript脚本解决方案
2014/04/20 Javascript
jquery滚动特效集锦
2015/06/03 Javascript
举例详解AngularJS中ngShow和ngHide的使用方法
2015/06/19 Javascript
javascript单例模式的简单实现方法
2015/07/25 Javascript
JavaScript+html5 canvas制作色彩斑斓的正方形效果
2016/01/27 Javascript
vuejs使用FormData实现ajax上传图片文件
2017/08/08 Javascript
详解react-native WebView 返回处理(非回调方法可解决)
2018/02/27 Javascript
使用Vue制作图片轮播组件思路详解
2018/03/21 Javascript
Vue列表渲染的示例代码
2018/11/01 Javascript
vue项目刷新当前页面的三种方法
2018/12/04 Javascript
jQuery实现带3D切割效果的轮播图功能示例【附源码下载】
2019/04/04 jQuery
CKEditor扩展插件:自动排版功能autoformat插件实现方法详解
2020/02/06 Javascript
Jquery使用each函数实现遍历及数组处理
2020/07/14 jQuery
vue select 获取value和lable操作
2020/08/28 Javascript
python基于右递归解决八皇后问题的方法
2015/05/25 Python
python文件操作相关知识点总结整理
2016/02/22 Python
Python3中条件控制、循环与函数的简易教程
2017/11/21 Python
Python 数值区间处理_对interval 库的快速入门详解
2018/11/16 Python
找Python安装目录,设置环境路径以及在命令行运行python脚本实例
2020/03/09 Python
python向企业微信发送文字和图片消息的示例
2020/09/28 Python
jupyter notebook快速入门及使用详解
2020/11/13 Python
Html5 滚动穿透的方法
2019/05/13 HTML / CSS
HTML5 video进入全屏和退出全屏的实现方法
2020/07/28 HTML / CSS
女士时装鞋:Chinese Laundry
2018/08/29 全球购物
Petmate品牌官方网站:宠物用品
2018/11/25 全球购物
《鹬蚌相争》教学反思
2014/04/22 职场文书
快餐公司创业计划书
2014/04/29 职场文书
创业计划书之酒店
2019/08/30 职场文书
Mysql实现主从配置和多主多从配置
2021/06/02 MySQL
SQL Server代理:理解SQL代理错误日志处理方法
2021/06/30 SQL Server