7z文件格式及其源码的分析(六)-完结篇 – SkyChaserYu的博客

两份回答

上一篇在这边 7z文件体式及其源码的剖析(五)

本文次要引见streami的规律。

用于流式处置, 次要的问题是处置 因它是使现代化的。, 因而,缺席回头路。 不值得议论的说紧缩后

7z文件的文件头实在是分为两局部的, 字幕的这两个局部在pre中引见

  1. 头Header, 写在文件后头。 斩首。 下面所说的事头比较小。, 次要记载文件的版本通讯。, 随着尾头部的驻扎军队偏移和打勾和 它的次要功用是辨别文件类型并查找

  2. 行李箱, 它写在文件的末了。 斩首。 这是大浅盘。 7z 文件的买到紧缩通讯, 解紧缩次要信任于采用的通讯。

7z 公共用地的紧缩做事办法有 基本的下头Header有些承包是保存的, 继紧缩资料。 紧缩后, 行李箱 写完接近末期的, 再把 行李箱 的浆糊,偏移,检验并回写头Header上吧。

在流媒体包围着的中, 在鞋楦一步写回头Header下面所说的事做事办法显然是不值得议论的做完的。 因它早已滔滔不绝了。

那 7z 是怎样处置下面所说的事问题的呢? 7z 你支撑流紧缩吗?

7z 在文件中,下面所说的事问题缺席毫不含糊的答案。 让咱们看一眼它的密码电文。

咱们找到 7z 泄压信号,  文件. 找到 HRESULT CInArchive::ReadDatabase2()功用。 可能性在1136行.

此职务在读取头Header 通讯, 寻觅行李箱驻扎军队。

咱们在正面的截取局部信号节片

HRESULT CInArchive::ReadDatabase2(
    DECL_EXTERNAL_CODECS_LOC_VARS
    CArchiveDatabaseEx &db
    #ifndef _NO_CRYPTO
    , ICryptoGetTextPassword *getTextPassword, bool &passwordIsDefined
    #endif
    )
{
  ();
  db.ArchiveInfo.StartPosition = _arhiveBeginStreamPosition;

   = 字幕〔6〕
  db.ArchiveInfo.Version.Minor = 字幕[7]

  if ( != kMajorVersion)
    ThrowUnsupportedVersion();

  UInt32 crcFromArchive = Get32(_header + 8);
  UInt64 nextHeaderOffset = Get64(_header + 0xC);
  UInt64 nextHeaderSize = Get64(_header + 0x14);
  UInt32 nextHeaderCRC = Get32(_header + 0x1C);
  UInt32 crc = CrcCalc(_header + 0xC, 20);

  #ifdef FORMAT_7Z_RECOVERY
  if (CRC公司FromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)
  {
    UInt64 cur, cur2;
    RINOK(_stream->Seek(0, STREAM_SEEK_CUR, 电流)
    const int kCheckSize = 500;
    Byte buf[kCheckSize];
    RINOK(_stream->Seek(0, STREAM_SEEK_END, &cur2));
    int checkSize = kCheckSize;
    if (cur2 - cur < kCheckSize)
      checkSize = (int)(cur2 - cur);
    RINOK(_stream->Seek(-checkSize, STREAM_SEEK_END, &cur2));

    RINOK(ReadStream_FALSE(_stream, buf, (size_t)checkSize));

    int i;
    for (i = (int)checkSize - 2; i >= 0; i--)
      if (布夫[I] == 0x17 && 布夫[我] + 1] == 0x6 || 布夫[我]] == 0x01 && 布夫[我] + 1] == 0x04)
        break;
    if (i < 0)
      return S_FALSE;
    nextHeaderSize = checkSize - i;
    nextHeaderOffset = cur2 - cur + i;
    nextHeaderCRC = CrcCalc(buf + i, (size_t)nextHeaderSize);
    RINOK(_stream->搜索(cur, STREAM_SEEK_SET, 空)
  }
  else
  #endif
  {
    if (CRC公司 != crcFromArchive)
      ThrowIncorrect();
  }

  db.ArchiveInfo.StartPositionAfterHeader = _arhiveBeginStreamPosition + kHeaderSize;


(...)

}

可以留心, 以下句子出生于头Header上读行李箱通讯。

  UInt32 crcFromArchive = Get32(_header + 8);
  UInt64 nextHeaderOffset = Get64(_header + 0xC);
  UInt64 nextHeaderSize = Get64(_header + 0x14);
  UInt32 nextHeaderCRC = Get32(_header + 0x1C);
  UInt32 crc = CrcCalc(_header + 0xC, 20);

接着, 继是另一个人判别。

if (CRC公司FromArchive == 0 && nextHeaderOffset == 0 && nextHeaderSize == 0 && nextHeaderCRC == 0)

设想这些都看不懂怎样办?

看信号, 接下来, 从文件末了开端。, 前进逆找角色

if (布夫[I] == 0x17 && 布夫[我] + 1] == 0x6 || 布夫[我]] == 0x01 && 布夫[我] + 1] == 0x04)

这执意咱们要找的。0x17 0x06 或许 0x01 0x04这两个特点字母行。

信号不寻常的。

设想你找到采用一个人, 纵然找到了行李箱如今。

为什么咱们能这么样做?, 这两根弦代表什么?

经过检查7Z文档(实则), 后头提到的行李箱也有可能性找出建筑学是什么时分

  1. 0x17是紧缩头的指出kEncodedHeader. 后头的 0x06 是 packstream 的印记 kPackInfo.
  2. 0x01这是一个人普通斩首的印记。kHeader. 而 0x04 是 mainstream 的印记 kMainStreamsInfo.

这几近它的本来面目。 7z 的两种 行李箱体式。

到这边, 可以综合起来。

7z 流式紧缩
紧缩可用于头Header 达到目标 偏移量和 crc 和等 片刻。
减压时, 设想检测到这些空白, 搜索从文件末了开端。行李箱特点字母行。

该办法在一定程度上可以取得。 流紧缩。 但 7z 文件建筑学自身,限度局限其不快用于滔滔不绝紧缩。

迎将议论和交流:尼尔 的视频博客

byNeil
byNeil.com

From Blog by Neil, post 7z文件体式及其源码的剖析(六)-使筋疲力尽篇

原文出生于 Blog by Neil, post 7z文件体式及其源码的剖析(六)-使筋疲力尽篇 转载请选定出处。咱们保存买到右手

发表评论

电子邮件地址不会被公开。 必填项已用*标注