【问题标题】:Compressing UTF-8(or other 8-bit encoding) to 7 or fewer bits将 UTF-8(或其他 8 位编码)压缩到 7 位或更少位
【发布时间】:2010-12-22 16:50:06
【问题描述】:

我希望获取一个以 UTF-8 编码且不使用超过 128 个不同字符的文件,然后将其移至 7 位编码以节省 1/8 的空间。例如,如果我有一个 16 MB 的文本文件,它只使用前 128(ascii) 个字符,我想削减多余的位以将文件减小到 14MB。

我该怎么做呢?

似乎没有现有的免费或专有程序可以这样做,所以我想我可以尝试制作一个简单(如果效率低下)的程序。

我的基本想法是从每个字符当前使用的十六进制/十进制/二进制值到我在七位编码中拥有的 128 个值创建一个函数,然后扫描文件并将每个修改后的值写入一个新文件。

如果文件看起来像这样(我将使用十进制示例,因为我尽量不必用十六进制思考)

127 254 025 212 015 015 132... 会变成

001 002 003 004 005 005 006

如果 127 映射到 001,254 映射到 005,等等

不过,我对一些事情并不完全确定。

  1. 这是否足以真正缩短文件大小?我有一种不好的感觉,这只会在二进制字符串上留下一个额外的 0——11011001 可能会映射到 01000001 而不是 1000001,而且我实际上不会节省空间。 如果发生这种情况,我该如何摆脱零?
  2. 如何打开文件以二进制/十进制/十六进制读取/写入,而不仅仅是文本? 我主要使用 Python,但如果必须,我可以应付 C。

谢谢。

【问题讨论】:

  • 我认为您的问题不是关于 UTF-8,而是关于一般压缩。我建议您关注压缩部分和/或阅读更多关于文本编码和 UTF 编码的信息。
  • 您真正的问题与“编码”或“utf-8”无关。这都是关于数据压缩的。考虑到多年来已经尝试和测试了几种不同的压缩方法,更重要的是现在可以可靠地压缩和解压缩有价值的数据。与您的方法不同,它们对各种数据也很有用。如果要使用 Python 压缩文件,请使用 gzip 模块或 zipfile 模块。

标签: python c utf-8 compression


【解决方案1】:

只需使用 gzip 压缩,0% 的努力即可节省 60-70%!

【讨论】:

  • 我支持这个。与从 8 位到 7 位的简单映射相比,如果有非常好的压缩算法很可能会做得更好,那么就不需要花哨且容易出错的位摸索。
【解决方案2】:

你明白文件是按字节划分的吗?因此,如果你这样做了,你将在字节 1 中获得第一个字母的 7 位,加上第二个字​​母的 1 位,然后在字节 2 中,你将拥有第二个字母的 6 位和 2 位第三,以此类推。它看起来像这样:

|AAAAAAAB|BBBBBBCC|CCCCCDDD|DDDDEEEE|EEEFFFFF|FF...
 \------/ \------/ \------/ \------/ \------/
   byte     byte     byte     byte     byte

【讨论】:

  • +1 表示有趣的 ASCII 图。如果你使用了 OP 的方案,你可以节省大约 2 个字节。
【解决方案3】:

您的想法在正确的轨道上,但需要一些发展。如果您对这种数据压缩感兴趣,您可能需要调查Huffman coding。这是一种简单的数据压缩技术,可用于许多实际情况。

我可以推荐 Mark Nelson 的 The Data Compression Book,这是对数据压缩技术的精彩介绍。

【讨论】:

    【解决方案4】:

    你的想法不太可能奏效。如果您将字节 0x05 写入文件,则会写入该字节的全部 8 位 - 带有前导零。要真正完成您需要的工作,您可以将每个 8 个字节编码为 7 个字节(因为您只需要 8*7 位来编码 8 个值)。一种方法是将 7 个值保留在其字节的 7 个低位中,并将第 8 个字节分布在 7 个 MSBit 上。

    对于 Python,以二进制写入模式打开文件是open(filename, 'wb')。您还必须了解按上述方式打包字节的位操作。

    只是一个小例子:

    >>> a = 0x03
    >>> b = 0x59
    >>> c = ((a & 0x1) << 7) | b
    >>> hex(c)
    '0xd9'
    >>> 
    

    这会将a 的最低位放入c 的MSBit,c 的其余部分是b 的值。

    我相信你可以从这里拿走它。

    【讨论】:

    • 这正是我想要的。谢谢。
    【解决方案5】:

    “这只会在二进制字符串上留下一个额外的 0——11011001 可能会映射到 01000001 而不是 1000001,我实际上不会节省空间。”

    正确。您的计划将无济于事。

    【讨论】:

      【解决方案6】:

      您需要的是 UTF-7。

      编辑: UTF-7 具有膨胀“仅”特殊字符的优点,因此如果输入中的特殊字符很少见,那么与仅将 UTF-8 转换为 7 相比,您获得的字节数要少得多少量。这就是 UTF-7 的用途。

      【讨论】:

      • UTF-7 是一种设计用于在 7 位宽的通道上传输的编码。无论 OP 真正需要什么,都不是这样。 u'\xa0'.encode('utf8') -> '\xc2\xa0' # 2 bytes;但是u'\xa0'.encode('utf7') -> '+AKA-' # FIVE bytes ... OP 希望将大小减小 12.5%;你会增加 150% 的大小。
      • 有什么优势?没有 UTF-7 编码的字节数少于 UTF-8 编码的 Unicode 字符。假设输入仅包含字母 ASCII 字符。 'abcde' 在 UTF-7 中占用 5 个字节,在 UTF-8 中占用 5 个字节——这与“少得多字节”的故事有什么关系?
      猜你喜欢
      • 1970-01-01
      • 2017-01-09
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-04
      相关资源
      最近更新 更多