# 13.4. `lzma` - 使用LZMA算法进行压缩

版本3.3中的新功能。

源代码： Lib / lzma.py

此模块提供类和便利功能，用于使用LZMA压缩算法压缩和解压缩数据。还包括支持xz实用程序使用的`.xz`和旧版`.lzma`文件格式以及原始压缩流的文件接口。

该模块提供的接口与`bz2`模块的接口非常相似。但是，请注意，`LZMAFile`是不是线程安全，与`bz2.BZ2File`不同，因此，如果您需要使用单个`LZMAFile`

exception `lzma.``LZMAError`

  当在压缩或解压缩期间或在初始化压缩器/解压缩器状态期间发生错误时引发此异常。

## 13.4.1. Reading and writing compressed files

`lzma.``open`(filename, mode="rb", *, format=None, check=-1, preset=None, filters=None, encoding=None, errors=None, newline=None)

  以二进制或文本模式打开LZMA压缩文件，返回file object。

  filename参数可以是实际的文件名（给定为`str`或`bytes`对象），在这种情况下，或者它可以是要读取或写入的现有文件对象。

  The mode argument can be any of `"r"`, `"rb"`, `"w"`, `"wb"`, `"x"`, `"xb"`, `"a"` or `"ab"` for binary mode, or `"rt"`, `"wt"`, `"xt"`, or `"at"` for text mode. 默认值为`"rb"`。

  打开要读取的文件时，格式和过滤器参数与`LZMADecompressor`具有相同的含义。在这种情况下，不应使用检查和预设参数。

  打开要写入的文件时，格式，检查，预设和过滤器 `LZMACompressor`。

  对于二进制模式，此函数等效于`LZMAFile`构造函数：`LZMAFile（filename， mode， ...）` 。在这种情况下，不能提供编码，错误和新行参数。

  对于文本模式，将创建一个`LZMAFile`对象，并将其包装在具有指定编码，错误处理行为和行结尾的`io.TextIOWrapper`实例中。

  在版本3.4中更改：添加对`"x"`，`"xb"`和`"xt"`模式的支持。

class `lzma.``LZMAFile`(filename=None, mode="r", *, format=None, check=-1, preset=None, filters=None)

  以二进制模式打开LZMA压缩文件。

  `LZMAFile`可以包装已打开的file object，或直接在命名文件上操作。filename参数指定要打开的文件对象或要打开的文件的名称（作为`str`或`bytes`对象）。当包装现有文件对象时，当`LZMAFile`关闭时，包装文件不会关闭。

  The mode argument can be either `"r"` for reading (default), `"w"` for overwriting, `"x"` for exclusive creation, or `"a"` for appending. 这些可以等效地分别给出为`"rb"`，`"wb"`，`"xb"`和`"ab"` 。

  If filename is a file object (rather than an actual file name), a mode of `"w"` does not truncate the file, and is instead equivalent to `"a"`.

  当打开用于读取的文件时，输入文件可以是多个单独的压缩流的级联。这些被透明地解码为单个逻辑流。

  打开要读取的文件时，格式和过滤器参数与`LZMADecompressor`具有相同的含义。在这种情况下，不应使用检查和预设参数。

  打开要写入的文件时，格式，检查，预设和过滤器 `LZMACompressor`。

  `LZMAFile`支持`io.BufferedIOBase`指定的所有成员，但`detach()`和`truncate()`除外。支持迭代和`with`语句。

  还提供以下方法：

  `peek`(size=-1)

    返回缓冲数据，而不提前文件位置。将返回至少一个字节的数据，除非已达到EOF。返回的确切字节数未指定（忽略size参数）。

    注意

    调用`peek()`不会更改`LZMAFile`的文件位置，它可能会更改底层文件对象的位置。如果`LZMAFile`是通过传递filename的文件对象构建的）。

  在版本3.4中已更改：添加了对`"x"`和`"xb"`模式的支持。

  在版本3.5中更改： `read()`方法现在接受`None`的参数。

## 13.4.2. Compressing and decompressing data in memory

class `lzma.``LZMACompressor`(format=FORMAT_XZ, check=-1, preset=None, filters=None)

  创建压缩器对象，可用于逐步压缩数据。

  有关压缩单个数据块的更方便的方法，请参见`compress()`。

  格式参数指定应使用哪种容器格式。可能的值有：

  - `FORMAT_XZ`：`.xz`容器格式。

      这是默认格式。

  - `FORMAT_ALONE`：旧版`.lzma`容器格式。

      此格式比`.xz`更受限制 - 它不支持完整性检查或多个过滤器。

  - `FORMAT_RAW`：原始数据流，不使用任何容器格式。

      此格式说明符不支持完整性检查，并要求您始终指定自定义过滤器链（用于压缩和解压缩）。此外，以这种方式压缩的数据不能使用`FORMAT_AUTO`解压缩（请参阅`LZMADecompressor`）。

  check参数指定要包括在压缩数据中的完整性检查的类型。此检查用于解压缩时，以确保数据未被损坏。可能的值有：

  - `CHECK_NONE`：无完整性检查。这是`FORMAT_ALONE`和`FORMAT_RAW`的默认（且唯一可接受的值）。
  - `CHECK_CRC32`：32位循环冗余校验。
  - `CHECK_CRC64`：64位循环冗余校验。这是`FORMAT_XZ`的默认值。
  - `CHECK_SHA256`：256位安全散列算法。

  如果不支持指定的检查，则会引发`LZMAError`。

  压缩设置可以指定为预设压缩级别（使用预设参数），也可以详细指定为自定义过滤器链（使用过滤器参数）。

  预设参数（如果提供）应为`0`和`9`（含）之间的整数，可选择与常数`PRESET_EXTREME`。If neither preset nor filters are given, the default behavior is to use `PRESET_DEFAULT` (preset level `6`). 较高的预设产生较小的输出，但使压缩过程较慢。

  注意

  除了更多的CPU密集，具有更高预设的压缩还需要更多的内存（并产生需要更多内存来解压缩的输出）。例如，使用预设`9`，`LZMACompressor`对象的开销可能高达800 MiB。因此，通常最好坚持使用默认预设。

  过滤器参数（如果提供）应为过滤器链说明符。有关详细信息，请参见Specifying custom filter chains。

  `compress`(data)

    压缩数据（a `bytes`对象），返回包含至少部分输入的压缩数据的`bytes`对象。一些数据可以在内部缓冲，用于稍后调用`compress()`和`flush()`。返回的数据应与之前对`compress()`的任何调用的输出连接。

  `flush`()

    完成压缩过程，返回一个包含存储在压缩器内部缓冲区中的任何数据的`bytes`对象。

    在调用此方法后，无法使用压缩器。

class `lzma.``LZMADecompressor`(format=FORMAT_AUTO, memlimit=None, filters=None)

  创建解压缩器对象，可用于逐步解压缩数据。

  有关一次解压缩整个压缩流的更方便的方法，请参阅`decompress()`。

  格式参数指定应使用的容器格式。默认值为`FORMAT_AUTO`，它可以解压缩`.xz`和`.lzma`文件。其他可能的值包括`FORMAT_XZ`，`FORMAT_ALONE`和`FORMAT_RAW`。

  memlimit参数指定解压缩程序可以使用的内存量的限制（以字节为单位）。使用此参数时，如果无法在给定的内存限制内解压缩输入，则解压缩将失败并使用`LZMAError`。

  filters参数指定用于创建要解压缩的流的过滤器链。如果格式是`FORMAT_RAW`，则此参数是必需的，但不应用于其他格式。有关过滤器链的详细信息，请参见Specifying custom filter chains。

  注意

  与`decompress()`和`LZMAFile`不同，此类不透明地处理包含多个压缩流的输入。要使用`LZMADecompressor`解压缩多流输入，必须为每个流创建一个新的解压缩器。

  `decompress`(data, max_length=-1)

    解压缩数据（a bytes-like object），以字节形式返回未压缩数据。一些数据可以在内部缓冲，以便稍后调用`decompress()`。返回的数据应与之前对`decompress()`的任何调用的输出连接。

    如果max_length为非负数，则返回至多max_length字节的解压缩数据。如果达到此限制并且可以产生进一步输出，则`needs_input`属性将设置为`False`。在这种情况下，对`decompress()`的下一个调用可以提供数据作为`b''`以获得更多的输出。

    如果所有输入数据都解压缩并返回（因为它小于max_length字节，或因为max_length为负数），则`needs_input`属性将设置为`True`。

    在流到达结束后尝试解压缩数据引发EOFError。在流结束后找到的任何数据都将被忽略，并保存在`unused_data`属性中。

    在版本3.5中已更改：添加了max_length参数。

  `check`

    输入流使用的完整性检查的ID。这可以是`CHECK_UNKNOWN`，直到足够的输入已经被解码以确定它使用什么完整性检查。

  `eof`

    `True`如果已达到流结束标记。

  `unused_data`

    压缩流结束后找到的数据。

    在到达流的结束之前，这将是`b""`。

  `needs_input`

    `False`如果`decompress()`方法可以在需要新的未压缩输入之前提供更多解压缩数据。

    版本3.5中的新功能。

`lzma.``compress`(data, format=FORMAT_XZ, check=-1, preset=None, filters=None)

  压缩数据（a `bytes`对象），将压缩数据作为`bytes`对象返回。

  有关格式，检查，预设和过滤器的说明，请参阅上述`LZMACompressor`参数。

`lzma.``decompress`(data, format=FORMAT_AUTO, memlimit=None, filters=None)

  解压缩数据（a `bytes`对象），将未压缩数据作为`bytes`对象返回。

  如果data是多个不同压缩流的并置，解压缩所有这些流，并返回结果的并置。

  有关格式，memlimit和过滤器参数的说明，请参见上述`LZMADecompressor`。

## 13.4.3. Miscellaneous

`lzma.``is_check_supported`(check)

  如果在此系统上支持给定的完整性检查，则返回true。

  始终支持`CHECK_NONE`和`CHECK_CRC32`。如果您使用的是使用有限功能集编译的liblzma版本，则`CHECK_CRC64`和`CHECK_SHA256`可能无法使用。

## 13.4.4. Specifying custom filter chains

过滤器链说明符是字典序列，其中每个字典包含单个过滤器的ID和选项。每个字典必须包含键`"id"`，并且可以包含用于指定过滤器相关选项的其他键。有效的过滤器ID如下：

- 压缩过滤器：
    - `FILTER_LZMA1`（用于`FORMAT_ALONE`）
    - `FILTER_LZMA2`（用于`FORMAT_XZ`和`FORMAT_RAW`）
- Delta滤波器：
    - `FILTER_DELTA`
- 分支呼叫跳转（BCJ）过滤器：
    - `FILTER_X86`
    - `FILTER_IA64`
    - `FILTER_ARM`
    - `FILTER_ARMTHUMB`
    - `FILTER_POWERPC`
    - `FILTER_SPARC`

过滤器链最多可包含4个过滤器，且不能为空。链中的最后一个过滤器必须是压缩过滤器，并且任何其他过滤器必须是delta或BCJ过滤器。

压缩过滤器支持以下选项（在字典中表示过滤器的附加条目）：

> - `preset`: A compression preset to use as a source of default values for options that are not specified explicitly.
> - `dict_size`: Dictionary size in bytes. This should be between 4 KiB and 1.5 GiB (inclusive).
> - `lc`: Number of literal context bits.
> - `lp`: Number of literal position bits. The sum `lc + lp` must be at most 4.
> - `pb`: Number of position bits; must be at most 4.
> - `mode`: `MODE_FAST` or `MODE_NORMAL`.
> - `nice_len`: What should be considered a “nice length” for a match. This should be 273 or less.
> - `mf`: What match finder to use – `MF_HC3`, `MF_HC4`, `MF_BT2`, `MF_BT3`, or `MF_BT4`.
> - `depth`: Maximum search depth used by match finder. 0 (default) means to select automatically based on other filter options.

增量滤波器存储字节之间的差异，在某些情况下为压缩器产生更多的重复输入。它只支持单个增量过滤器只支持一个选项`dist`。这指示要减去的字节之间的距离。默认值为1，即取相邻字节之间的差异。

BCJ过滤器旨在应用于机器代码。它们转换代码中的相对分支，调用和跳转以使用绝对寻址，目的是增加压缩器可利用的冗余。这些过滤器支持一个选项，`start_offset`。它指定应映射到输入数据开头的地址。默认值为0。

## 13.4.5. Examples

在压缩文件中读取：

    import lzma
    with lzma.open("file.xz") as f:
        file_content = f.read()

创建压缩文件：

    import lzma
    data = b"Insert Data Here"
    with lzma.open("file.xz", "w") as f:
        f.write(data)

压缩内存中的数据：

    import lzma
    data_in = b"Insert Data Here"
    data_out = lzma.compress(data_in)

增量压缩：

    import lzma
    lzc = lzma.LZMACompressor()
    out1 = lzc.compress(b"Some data\n")
    out2 = lzc.compress(b"Another piece of data\n")
    out3 = lzc.compress(b"Even more data\n")
    out4 = lzc.flush()
    # Concatenate all the partial results:
    result = b"".join([out1, out2, out3, out4])

将压缩数据写入已打开的文件：

    import lzma
    with open("file.xz", "wb") as f:
        f.write(b"This data will not be compressed\n")
        with lzma.open(f, "w") as lzf:
            lzf.write(b"This *will* be compressed\n")
        f.write(b"Not compressed\n")

使用自定义过滤器链创建压缩文件：

    import lzma
    my_filters = [
        {"id": lzma.FILTER_DELTA, "dist": 5},
        {"id": lzma.FILTER_LZMA2, "preset": 7 | lzma.PRESET_EXTREME},
    ]
    with lzma.open("file.xz", "w", filters=my_filters) as f:
        f.write(b"blah blah blah")