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 对于不同操作系统上的相同输入产生不同的结果 的相关文章

  • Eslint errorring 导入没有扩展名的 jsx

    我正在尝试在 es6 中导入 jsx 文件而不需要 jsx 扩展名 import LoginErrorDialog from LoginErrorDialogView Not import LoginErrorDialog from Log
  • 如何修改每个JSON对象javascript

    我想修改里面的每个 JSON 值cooldown object cooldown user 1 This user2 0 This 在 Javascript 中使用 for 语句 我研究了好几个小时 只找到了内部的 blocks Edit
  • 如何在react-bootstrap中禁用表单提交的

    在下面的代码片段中 我有许多文本类型的输入表单 如果用户点击 我似乎会得到相同的合成事件 就像他们按下提交按钮一样 我想忽略作为表单提交 只允许一个人按下 提交 按钮 我删除了一些表单组以减少示例 在所有情况下 按钮或 ENTER 键 e
  • 如何将内联 JavaScript 与 Express/Node.js 中动态生成的内容分开?

    对于具有几年 Web 开发经验但没有找到答案的人来说 这是一个有点菜鸟的问题程序员堆栈交换 or Google 我决定在这里问一下 我在用Express网络框架Node js 但这个问题并不特定于任何 Web 框架或编程语言 以下是从数据库
  • 带有淘汰赛js的隐形recaptcha

    我正在完成隐形验证码 但我在实现它时遇到问题 谷歌开发人员页面中的代码显示它应该是这样的
  • 如何针对 Node.js 中发生的每个错误发送电子邮件?

    假设我的 node js 应用程序正在运行 如果出现错误 我的意思是所有错误 不仅仅是网络错误 如果出现错误 则很重要 我如何调用函数向我发送电子邮件 基本上 在我希望它写入 err out 之前 我希望向我发送一封电子邮件 我正在使用no
  • Snap.svg - 停止在可悬停元素的子元素上重新触发悬停事件

    对于一个项目 我使用的 SVG 形状由背景多边形和背景多边形上方的一些文本 我已将其转换为路径 组成 我正在使用 Snap svg 为我的形状设置动画 当我将鼠标悬停在多边形上时 形状应该缩放到特定尺寸 包括其中的所有内容 鼠标移开时 形状
  • 无法理解Peterson算法的正确性

    我在这里讨论彼得森算法的一个场景 flag 0 0 flag 1 0 turn P0 flag 0 1 turn 1 while flag 1 1 turn 1 busy wait
  • 使用 CSS 或 Javascript 填充动画

    我只是想知道是否可以使用 CSS 或 javascript 创建填充动画 基本上我想创建一个填充动画 如下图所示 http i40 tinypic com eit6ia png http i40 tinypic com eit6ia png
  • Javascript split 不是一个函数

    嘿朋友们 我正在使用 javascript sdk 通过 jQuery facebook 多朋友选择器在用户朋友墙上发布信息 但是我收到此错误friendId split 不是函数 这是我的代码 function recommendToFr
  • 将 UMD Javascript 模块导入浏览器

    你好 我正在对 RxJS 进行一些研究 我可以通过在浏览器中引用它来使用该库 如下所示 它使用全局对象命名空间变量 Rx 导入 我可以制作可观察的东西并做所有有趣的事情 当我将 src 更改为指向最新的 UMD 文件时 一切都会崩溃 如下所
  • 可以设置标题样式吗? (并且使用CSS或js?)[重复]

    这个问题在这里已经有答案了 我想知道是否可以设计一个title a href title This is a title Hello a 样式问题有两个方面 文本格式 编码 我猜这是可能的 所以在问题中这样做 工具提示样式 你能把它弄大一点
  • Firebase 函数 onWrite 未被调用

    我正在尝试使用 Firebase 函数实现一个触发器 该触发器会复制数据库中的一些数据 我想观看所有添加的内容votes user vote 结构为 我尝试的代码是 const functions require firebase func
  • 日期出现奇怪的错误,“未捕获非法访问”

    所以我试图找到最新的DateJavascript 可以处理 我把它减少到 9 月 275760 并增加了我开始捕获未捕获的天数illegal access例外new Date 09 24 275760 to new Date 10 13 2
  • Vue 和 Vuex:处理依赖的计算属性

    我的应用程序是一个使用 Vuex 在 Vue 中构建的精简电子表格 关键组件是TableCollection Table and Row The TableCollection有一个包含多个的数组Table对象 每个Table有一个包含多个
  • 代码镜像错误:未捕获错误:扩展集中无法识别扩展值([对象对象])

    全部 我目前正在从事一个React Electron项目 该项目的目标是完成一个Markdown编辑器 当我配置codemirror 该程序报告错误说 Uncaught Error Unrecognized extension value
  • 在 Shopify 商店中嵌入 Vue 组件

    在产品页面中 我尝试显示自定义 Vue 组件 为简洁起见 该组件根据给定的产品 ID 显示 Firebase 数据库中的一些信息 我最初尝试将其制作为 Shopify 应用程序 以便我可以访问他们的 API 我实现了 OAuth 并且可以检
  • 在 CKEditor 中设置字体大小和字体系列

    我正在使用 ckeditor 我想问一下这个插件如何设置font family和font size 我尝试过使用 CKEDITOR config font defaultLabel Arial CKEDITOR config fontSiz
  • JavaScript 相对路径

    在第一个 html 文件中 我使用了一个变量类别链接 var categoryLinks Career prospects http localhost Landa DirectManagers 511 HelenaChechik Dim0
  • 如何在react-highcharts中使用图表工具提示格式化程序?

    如何使用图表工具提示格式化程序 我正在使用高图表的反应包装器 我有这样的配置 const CHART CONFIG tooltip formatter tooltip gt var s b this x b each this points

随机推荐

  • 直接通过 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