标识头
50 4B 01 02 kCentralFileHeader
50 4B 03 04 kLocalFileHeader
50 4B 05 06 kEndOfCentralDir
kEndOfCentralDir:
文件最后位置, cdStartOffset 定位 kCentralFileHeader
struct CEcd
{
UInt16 thisDiskNumber;
UInt16 startCDDiskNumber;
UInt16 numEntriesInCDOnThisDisk;
UInt16 numEntriesInCD;
UInt32 cdSize;
UInt32 cdStartOffset;
UInt16 commentSize;
void Parse(const Byte *p);
};
void CEcd::Parse(const Byte *p)
{
thisDiskNumber = Get16(p);
startCDDiskNumber = Get16(p + 2);
numEntriesInCDOnThisDisk = Get16(p + 4);
numEntriesInCD = Get16(p + 6);
cdSize = Get32(p + 8);
cdStartOffset = Get32(p + 12);
commentSize = Get16(p + 16);
}
kCentralFileHeader:
集中数据 压缩包内项目, LocalHeaderPosition 为实际数据偏移 kLocalFileHeader
<span style="font-family: Arial, Helvetica, sans-serif;">HRESULT CInArchive::ReadCdItem(CItemEx &item)</span>
{
item.FromCentral = true;
const int kBufSize = 42;
Byte p[kBufSize];
SafeReadBytes(p, kBufSize);
item.MadeByVersion.Version = p[0];
item.MadeByVersion.HostOS = p[1];
item.ExtractVersion.Version = p[2];
item.ExtractVersion.HostOS = p[3];
item.Flags = Get16(p + 4);
item.CompressionMethod = Get16(p + 6);
item.Time = Get32(p + 8);
item.FileCRC = Get32(p + 12);
item.PackSize = Get32(p + 16);
item.UnPackSize = Get32(p + 20);
UInt16 headerNameSize = Get16(p + 24);
UInt16 headerExtraSize = Get16(p + 26);
UInt16 headerCommentSize = Get16(p + 28);
UInt32 headerDiskNumberStart = Get16(p + 30);
item.InternalAttributes = Get16(p + 32);
item.ExternalAttributes = Get32(p + 34);
item.LocalHeaderPosition = Get32(p + 38);
ReadFileName(headerNameSize, item.Name);
if (headerExtraSize > 0)
{
ReadExtra(headerExtraSize, item.CentralExtra, item.UnPackSize, item.PackSize,
item.LocalHeaderPosition, headerDiskNumberStart);
}
if (headerDiskNumberStart != 0)
throw CInArchiveException(CInArchiveException::kMultiVolumeArchiveAreNotSupported);
// May be these strings must be deleted
/*
if (item.IsDir())
item.UnPackSize = 0;
*/
ReadBuffer(item.Comment, headerCommentSize);
return S_OK;
}
kLocalFileHeader
数据后面紧跟项目压缩后的数据
HRESULT CInArchive::ReadLocalItem(CItemEx &item)
{
const int kBufSize = 26;
Byte p[kBufSize];
SafeReadBytes(p, kBufSize);
item.ExtractVersion.Version = p[0];
item.ExtractVersion.HostOS = p[1];
item.Flags = Get16(p + 2);
item.CompressionMethod = Get16(p + 4);
item.Time = Get32(p + 6);
item.FileCRC = Get32(p + 10);
item.PackSize = Get32(p + 14);
item.UnPackSize = Get32(p + 18);
UInt32 fileNameSize = Get16(p + 22);
item.LocalExtraSize = Get16(p + 24);
ReadFileName(fileNameSize, item.Name);
item.FileHeaderWithNameSize = 4 + NFileHeader::kLocalBlockSize + fileNameSize;
if (item.LocalExtraSize > 0)
{
UInt64 localHeaderOffset = 0;
UInt32 diskStartNumber = 0;
ReadExtra(item.LocalExtraSize, item.LocalExtra, item.UnPackSize, item.PackSize,
localHeaderOffset, diskStartNumber);
}
/*
if (item.IsDir())
item.UnPackSize = 0; // check It
*/
return S_OK;
}