当前位置: 首页 > 知识库问答 >
问题:

为什么Base64编码的数据压缩得这么差?

秦博延
2023-03-14
  • 原始文件:429,7 MIB
  • 通过XZ-9
    13,2 MiB/429,7 MiB=0,0314,9 MiB/s1:28
  • base64它和压缩通过XZ-9:
    26,7 MiB/580,4 MiB=0,0462,6 MiB/s3:47
  • base64原始压缩xz文件:
    17,8 MIB几乎没有时间=预期的1.33x大小增加

所以可以观察到的是:

  • xz压缩的☺真好
  • base64-编码的数据压缩不好,它比未编码的压缩文件大2倍
  • base64-then-compress明显比compress-then-base64
  • 差且慢

我知道base64然后压缩文件是没有意义的,但大多数情况下,人们无法控制输入文件,而且我会认为,由于base64编码的文件的实际信息密度(或无论它被称为什么)几乎与非编码版本相同,因此可以类似地压缩。

共有1个答案

劳宇
2023-03-14

大多数通用压缩算法都使用一字节粒度。

让我们考虑以下字符串:

"XXXXYYYYXXXXYYYY"
  • 游程编码算法会说:“那是4'x',后面跟着4'y',后面跟着4'x',后面跟着4'y'”
  • Lempel-Ziv算法会说:“这是字符串'xxxxyyyy',后面跟着同一个字符串:所以让我们用对第一个字符串的引用替换第二个字符串。”
  • 哈夫曼编码算法会说:“那个字符串中只有2个符号,所以每个符号只能用一个比特。”
"WFhYWFlZWVlYWFhYWVlZWQ=="
Input bytes    : aaaaaaaa bbbbbbbb cccccccc
6-bit repacking: 00aaaaaa 00aabbbb 00bbbbcc 00cccccc
0         1         2         3         4         5         6
ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/

例如,我们的示例字符串以等于0x58的十六进制(字符“x”的ASCII代码)的三个字节组开始。或二进制:01011000。让我们应用Base64编码:

Input bytes      : 0x58     0x58     0x58
As binary        : 01011000 01011000 01011000
6-bit repacking  : 00010110 00000101 00100001 00011000
As decimal       : 22       5        33       24
Base64 characters: 'W'      'F'      'h'      'Y'
Output bytes     : 0x57     0x46     0x68     0x59

基本上,在原始数据流中明显的模式“3乘以字节0x58”在编码数据流中不再明显,因为我们已经将字节分解成6位包,并将它们映射到现在看起来是随机的新字节。

或者换句话说:我们打破了大多数压缩算法所依赖的原始字节对齐方式。

对于加密来说更是如此:首先压缩,其次加密

编辑-关于LZMA的注记

正如MSalters注意到的那样,xz正在使用的LZMA处理的是位流而不是字节流。

Input bytes      : 0x58     0x58     0x58
As binary        : 01011000 01011000 01011000
(see above for the details of Base64 encoding)
Output bytes     : 0x57     0x46     0x68     0x59
As binary        : 01010111 01000110 01101000 01011001
 类似资料:
  • 问题内容: 在通过网络发送数据包之前压缩数据包的最佳压缩算法是什么?数据包使用JSON编码。LZW会是一个不错的选择吗?还是有更好的选择? 问题答案: 我认为有两个问题会影响您的答案: 1)在不知道程序的任何特定运行情况下会如何预测数据的组成?例如,如果您的数据包如下所示: -那么您可能会通过创建一个不断出现在数据中的文本字符串的硬编码字典来获得最佳压缩,并用适当的字典索引替换每个出现的文本字符串

  • 问题内容: 因此,我刚刚意识到反编译Java代码是多么容易。我一直在网上搜索,但似乎无法弄清楚 为什么 这么容易。每次我在Google上搜索“为什么要反编译文件?”之类的信息时,或“为什么Java这么容易反编译”,我所得到的只是指向可以轻松反编译我的代码的软件的链接。因此,我向您介绍StackOverflow:为什么Java可以转换回容易阅读的源代码,而C ++和其他语言对反编译不是很友好? 谢谢

  • 我正在看宣传单。 在setTimeout中调用

  • 问题内容: 这段代码使我凝视了几分钟: (这里的第137行) 我以前从未见过,而且我也不知道Java有一个“ loop”关键字(NetBeans甚至没有像关键字一样给它上色),并且它在JDK 6中可以很好地编译。 有什么解释? 问题答案: 它不是一个keyword,而是一个label。 用法:

  • 在方法或类范围内,下面的行编译(带有警告): 在类作用域中,变量获取其默认值,以下给出未定义引用错误: 这难道不是第一个应该以相同的未定义引用错误结束吗?或者第二行应该编译?或者我错过了什么?

  • 问题内容: 我已经对流进行了一些测试,特别是对nio- package的DirectoryStreams进行了流测试。我只是尝试获取目录中所有文件的列表,该列表按上次修改日期和大小排序。 旧File.listFiles()的JavaDoc对File中 的 方法进行了注释: 请注意,Files类定义了newDirectoryStream方法来打开目录并遍历目录中的文件名。当使用非常大的目录时,这可能