zlib.gzip 对于不同操作系统上的相同输入产生不同的结果

2024-04-17

以下代码(在 Node js v0.10.28 上):

var zlib = require('zlib');
var buf = new Buffer('uncompressed');

zlib.gzip(buf, function (err, result) {
 console.log(result.toString('base64'));
});

产生字符串:

在 Win 7 x64 上:

H4sIAAAAAAAACyvNS87PLShKLS5OTQEA3a5CsQwAAAA=

^                                                          ^

on Mac

H4sIAAAAAAAAAyvNS87PLShKLS5OTQEA3a5CsQwAAAA

^                                                          ^

在 CentOs 上(Linux 2.6.32-279.19.1.el6.x86_64)

H4sIAAAAAAAAAyvNS87PLShKLS5OTQEA3a5CsQwAAAA=

^                                                          ^

看来结局不同=和第 13 个字符 (C vs A)但我不知道为什么。


一般差异的一些理论来源

gzip (RFC 1952 https://www.ietf.org/rfc/rfc1952.txt),它使用deflate (RFC 1951 https://www.ietf.org/rfc/rfc1951.txt)作为其压缩格式,从技术上讲只是一种文件格式规范。特别是,算法在如何选择压缩给定的字节方面被赋予了很大的自由度(这实际上是一种优势)。

有两种基本的压缩机制可以与deflate:

  • 长度有限的哈夫曼编码:出现频率较高的字符可以指定较短的位序列,出现频率较低的字符可以指定较长的位序列,从而导致表示相同信息的总体位数较少。用于编码的霍夫曼树可以根据输入(或其一部分)动态计算,也可以是固定的。因此,不同的编码器可能对相同的输入使用不同的霍夫曼树,从而导致树本身和编码字符的不同表示。

  • LZ77压缩:之前输出过的子串已经不需要再次输出;相反,只需要输出具有相同子字符串长度的反向引用。由于在给定输入中查找所有常见子字符串是一个 Hard Problem™,因此使用给定启发式查找尽可能多的子字符串通常会更有效(例如,跟踪以每个两个字符前缀开头的最后 6 个子字符串)。同样,不同的编码器可以(有效地)为相同的输入产生不同的输出。

最后,所有这些压缩数据被分散到一个或多个blocks,并且由编码器决定何时切换到新块。理论上,这甚至可以对每个字节进行(尽管这并不是真正的压缩!)。当结束一个块时,因为它的内容是使用霍夫曼位代码编码的,所以该块可能不会在字节边界上结束;在这种情况下,如果流中的后续项必须从整个字节开始(例如,未压缩的块必须从字节边界开始),则可以添加任意位作为填充以舍入到下一个字节。

正如您所看到的,相同输入的压缩字节可能有多种不同!即使使用相同的算法(例如规范的zlib库 http://www.zlib.net/,不要与同名的 RFC (1950) 混淆),不同的压缩级别通常会导致不同的结果。甚至可以想象,相同的程序在相同的环境中使用相同的输入和选项运行多次会产生不同的结果,例如由于数据结构对指针进行排序或使用指针作为散列值——指针值在执行之间可能会发生变化。此外,多线程实现本质上往往是不确定的。简而言之,您不应依赖给定输入的输出相同,除非您使用的实现明确提供了这种保证。 (尽管大多数理智的实现都力求确定性,但这在技术上并不是必需的。)

为什么您的具体示例 Base64 字符串有所不同

抛开尾随的差异=等一下,你的三个例子中有两个具有完全相同的表示。这两者仅相差一位(C -> A)在第十个字节的第一部分(Base64 将字节三元组编码为 Base-64 字符的四元组,因此第 13 个 Base64 字符是第十个字节的前六位)。A代表 0,并且C代表2-- 但请记住,这是字节的高六位,因此它实际上是 0 和 8 加上低两位。这些低两位是下一个 Base64 字符的高两位,y: y代表50,即110010以二进制表示,因此第十个字节的低两位是0b11,或 3。将它们放在一起,第十个字节是不同的,其值在一种实现中为 11,在另一种实现中为 3。快速浏览一下gzipRFC揭示了第十个字节指示执行编码的操作系统/文件系统:果然,11被定义为“NTFS文件系统(NT)”,3被定义为“Unix”。因此,这种情况下的差异完全是由于您执行编码的操作系统造成的。 (请注意,任何第二个双字gzipfile 是时间戳,在您的示例中设置为 0(不可用),但在所有三个试验中很容易有很大差异,从而使差异更难以发现。)

至于尾随的=,这只是 Base64 的填充(如维基百科上解释得很好 http://en.wikipedia.org/wiki/Base64)。由于 Base64 采用三个字节为一组并使用四个字节对其进行编码,因此如果编码的字节数不能被三整除,则使用最小数量的 Base64 数字(将输入末尾之后的字节视为空字节): byte,只需要两个Base64数字;对于两个人来说,只需要三个。这=添加符号只是将 Base64 数字的数量四舍五入到四的倍数;你会注意到这意味着=解码 Base64 字符串实际上并不需要符号,因为您知道它的长度(但如果字符串长度不是 4 的倍数,一些 Base64 解码器将拒绝该字符串)。因此,您的第二个和第三个示例表示完全相同的字节值,但由不同的 Base64 编码器生成。

你有它!我认为我的回答太冗长了,几乎可以归结为一个只有一句话答案的棘手问题,但我忍不住详细解释一切:-)

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

zlib.gzip 对于不同操作系统上的相同输入产生不同的结果 的相关文章

  • 节点未被识别为内部或外部命令,但位于 PATH 中

    尽管我遵循了以下建议 使用phonegap cordova时 node 不被识别为内部或外部命令 可操作程序或批处理文件 https stackoverflow com questions 23412938 node is not reco
  • Iphone 上的 Javascript 日期解析

    我正在开发一个针对移动设备的离线 Javascript 网站 iPhone 就是这样的一种移动设备 我正在尝试从 REST API JSON 对象的成员 解析日期 我在用着 Date parse 2010 03 15 10 30 00 这适
  • CSS 比例和方形中心裁剪图像

    所以我的应用程序中有一个缩略图集合 其大小为200x200 有时原始图像没有这个比例 所以我计划将此图像裁剪为正方形 目前它只是拉伸图像以适合缩略图 所以说我的原始图像大小是400x800 那么图像看起来就很压扁 我想裁剪此图像 以便它查看
  • 为什么 foo.hasOwnProperty('__proto__') 等于 false?

    var foo bar 5 Why is foo hasOwnProperty proto 等于false 它不能来自原型链中更高层的任何对象 因为它是特定于这个对象的 EDIT 有些答案说它已开启Object prototype 但我不明
  • History.pushState和页面刷新

    我开始研究 HTML5 新历史 API 不过 我有一个问题 如何处理页面刷新 例如 用户单击一个链接 该链接由 js 函数处理 该函数 异步加载页面内容 使用history pushState 更改URL 用户刷新页面 但是服务器上当然不存
  • 如何验证最终用户经过身份验证的令牌(使用 Firebase 身份验证)来调用 google cloud run 端点?

    请帮助使用 firebase 身份验证在云运行中进行最终用户身份验证 简短的介绍 我从 firebase 函数提交 Authorization Bearer idToken 标头 并使用电子邮件 密码 firebase 用户进行身份验证的
  • WaveSurfer JS 无法在 Firefox 中为特定的 mp3 音频文件生成图表

    我们面临着在 Firefox 中使用 wavesurfer JS 对某些特定格式的 mp3 文件绘制音频可视化 图表 的问题 它总是给我们这样的错误 传递给decodeAudioData 的缓冲区包含未知的内容类型 但同一个文件在 chro
  • 为什么有人将(Apache mod_expires 参数)ExpiresByType 设置为“访问加 0 秒”?

    在审查答案时这个帖子 https stackoverflow com questions 9933012 how to use mod headers and mod expires to cache 我不明白为什么这里使用 0 秒作为最佳
  • 使用 WebSocket 是否会产生服务器成本?

    我已经离开了 PHP MySQL 的舒适区 因为语法 封装 过程的东西可能会让人沮丧 上周 我开始尝试并按照一些教程使用 Node js Socket IO 创建实时聊天应用程序 到目前为止 我从未使用过 WebSockets 做过任何事情
  • 是否可以向 JavaScript 函数发送可变数量的参数?

    是否可以从数组向 JavaScript 函数发送可变数量的参数 var arr a b c var func function debug alert arguments length for arg in arguments alert
  • 在 Typescript 中从基类创建子类的新实例[重复]

    这个问题在这里已经有答案了 我想创建新实例Child班级来自Base类方法 这有点复杂 但我会尽力解释 这是一个例子 class Base constructor clone Here i want to create new instan
  • 从 bash 脚本运行节点

    很简单 我正在尝试使用 cron 自动运行 nodejs 脚本 但是脚本本身似乎无法运行该文件 我的脚本很简单 usr bin env node node var node assets js update js 但是 在运行此命令时 它返
  • 如何在特定天数限制后从温斯顿日志中删除文件?

    我正在使用winston将文件记录到按预期工作的服务器中 现在我想设置天数限制 假设3天后我想删除3天前记录的文件 是否可以使用winston轮换来实现 main js winston add winston transports File
  • 启动 onclick 比使用 document.onload 更快

    我有带有链接的 html 页面 我想在其中附加一个功能onclick事件 一种方法当然是 a href save php Save a 但我知道这不是最佳做法 所以我反而等待window onload 循环遍历链接并将保存功能附加到链接re
  • 无法安装js-bson

    我正在使用Windows 7 64位 尝试安装bson作为mongodb的依赖项 我收到此错误 npm WARN package json email protected cdn cgi l email protection No READ
  • JavaScript:嵌套循环?

    我想实现这样的动画 序列 动画以循环开始 想象一下car从 x1 移动到 x2 然后暂停 1 秒 然后再次播放动画 想象一下car从 x2 移动到 x3 等 the car循环是通过向汽车左侧添加 1px 来实现的 值 但我无法弄清楚嵌套循
  • jQuery clone() 复制数据...有时...?

    使用下面的示例 我有一个tr我正在复制 它包含一个 jQueryautocomplete 第一次克隆时 自动完成功能不起作用 因为附加的data items 一片空白 第二次单击 添加 按钮时 自动完成功能将起作用 此后 再次单击 添加 会
  • JQuery 屏蔽输入插件不起作用

    我已将 JQuery Masked 输入插件添加到我的 Web 项目中 但它根本不起作用 该插件可以在这里找到 http digitalbush com projects masked input plugin http digitalbu
  • Apollo 客户端“未找到命名导出‘删除’”

    我正在尝试创建一个apollo client插件Nuxt 3应用 它当前抛出有关名为的包的错误ts invariant file Users my name Repositories project node modules apollo
  • Escape String - 在 Javascript 中输出rails字符串[重复]

    这个问题在这里已经有答案了 我正在尝试将字符串值分配给 erb 文件中的 javascript 对象 如下所示 var data name 问题是 如果name is Tom s small ears 的输出data name将会Tom x

随机推荐

  • 直接通过 SSH 进入 docker 容器

    我有一些 docker 容器 现在我想通过 ssh 访问其中一个 这是工作我通过 ssh 连接到 docker 容器 但现在我遇到的问题是我不知道哪个用户可以访问这个容器 我已经对主机上的两个用户 网络和根 进行了尝试 但它们不起作用 知道
  • 如何使用 exec() 启动和停止 PHP 开发服务器

    如何使用 exec 函数启动和停止 PHP 开发服务器 我需要这样做才能自动化我的 BDD 测试 这将停止我的脚本的执行 echo exec php S localhost 8000 所以我需要一种方法从 PHP 启动服务器并能够继续执行我
  • 实体框架中的第二个 Self-To-Self 关系

    假设我们有一个域类 public class Incident Key public virtual int IncidentId get set Display Name Parent Incident public virtual In
  • 当我使用非共享运行时构建 Monodroid 项目时,获取编码失败

    我正在尝试在我的 Monodroid 应用程序中使用 DotNetZip 库 当我启用共享运行时构建选项时 一切似乎都工作正常 当我禁用共享运行时时 该行 static System Text Encoding ibm437 System
  • Angular 5 反应形式 - 单选按钮组

    我有 2 个单选按钮 我正在使用反应式表单 并且我已在组件中添加了表单控件 我面临的问题是 name 属性必须与 formControlName 相同 当我将名称属性设置为相同时 我只能选择 1 个单选按钮 永远无法取消选择并选择另一个 只
  • Flutter 出现 The method 'findRenderObject' was called on null

    最近有一个需求 需要测量条子里的子元素到顶部的距离 但是总是提示findrendereobject为空 我什至无法尝试 widgetsbinding instance addpostframecallback控制台错误 调度程序库捕获异常
  • 在 RxJava 2 中展平列表

    我已经使用 RxJava 1 一段时间了 但我想看看 RxJava 2 在 RxJava 1 中 我可以发出列表中的每个项目 如下所示 List
  • Spring MVC JSP 无法定位 Javascript 或 CSS

    这个问题似乎已经被问过几次了 但是在审查了太多次之后 我仍然看到这个问题 我的 Spring MVC 项目中的 jsp 无法找到任何 css 或 js 文件 即使它们在战争中并且给定的文件路径是正确的 根据我的配置 我看到两个错误 第一个是
  • 独立的 Visual Studio Code 工作区,针对不同的编程语言具有不同的扩展

    是否可以使用扩展分别创建不同的 Visual Studio Code 工作区 例如 工作区 1带有 C 扩展和工作区 2带有Python扩展 您可以安装扩展 然后在特定工作区上启用 禁用它们 打开工作区 在 扩展 面板中 单击每个扩展的齿轮
  • 在.VS 2015 NET 4.5中使用字符串插值和nameof

    我正在使用类似的东西 hello person and nameof arg1 在我的代码中 但在检查项目属性时 我的目标是 NET 4 5 这个可以吗 我以为这些东西是4 6引入的 该项目在我的机器上构建并运行良好 但我担心部署时会出现问
  • C# 中“decimal”类型的有趣行为

    如果我们将填充声明为 const 小数 则填充不起作用 mymoney 1 2 而你的钱 1 20 如何解释这种行为 class Program static void Main string args decimal balance 1
  • sklearn - 如何在one-hot编码时合并丢失的数据

    我试图保留数据集中包含缺失数据的行 当使用 sklearn 对一列 或多列 进行 one hot 编码时 是否可以写一个规则if currentItem null or if currentItem 0然后将输出数组设置为全0 e g A
  • 反对网站开发公司使用 JavaScript 框架的理由是什么? [关闭]

    Closed 这个问题是基于意见的 help closed questions 目前不接受答案 我们公司构建网站和网络应用程序 我们是一家小公司 我们的开发团队总是从头开始构建 JavaScript 函数 或者从我们构建的其他网站复制 每当
  • 数组中每个索引的函数调用之间的javascript延迟[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 目标 对数组中的每个元素执行逻辑 W
  • Highcharts - 图表回流功能的问题

    这是fiddle http jsfiddle net uBUv9 6 我有问题width图表与切换侧边栏 我在SO的帮助下解决了这个问题post https stackoverflow com questions 23602167 issu
  • 使用 Azure Devops API 创建构建定义

    我们尝试使用 Azure Devops Rest API 复制另一个构建定义信息来创建构建定义 但出现以下错误 HttpError BadRequest 值不能为空 参数名称 定义 Repository Mappings Mapping S
  • 使用acts_as_paranoid插件进行软删除-验证怎么样?

    我正在尝试使用acts as paranoid 插件来软删除记录 我之前使用数据库中的标志来管理它 我知道这个插件会从搜索中省略一条记录 并查找该记录是否被软删除 我想知道的是我是否在模型中进行了验证 例如validates uniquen
  • 处理 Kafka Broker 宕机时的故障

    我有一个 Kafka 代理正在运行 消息已成功消费 但我想处理 Kafka 代理在 Kafka 消费者端出现故障的情况 我读过了this https github com spring projects spring kafka issue
  • 加快保存图像的速度 - iOS

    我正在研究更多的小型项目 这些项目稍后将包含在一个新项目中 它基本上是一个测试单元 我正在做的是创建一个AVCaptureSession然后创建一个方法OutputSampleBufferDelegate 在该方法中 我将sampleBuf
  • zlib.gzip 对于不同操作系统上的相同输入产生不同的结果

    以下代码 在 Node js v0 10 28 上 var zlib require zlib var buf new Buffer uncompressed zlib gzip buf function err result consol