📄 zipout.cpp
字号:
// ZipOut.cpp#include "StdAfx.h"#include "ZipOut.h"#include "Common/StringConvert.h"#include "Common/CRC.h"#include "../../Common/OffsetStream.h"#include "../../Common/StreamUtils.h"namespace NArchive {namespace NZip {void COutArchive::Create(IOutStream *outStream){ m_Stream = outStream; m_BasePosition = 0;}void COutArchive::MoveBasePosition(UInt64 distanceToMove){ m_BasePosition += distanceToMove; // test overflow}void COutArchive::PrepareWriteCompressedDataZip64(UInt16 fileNameLength, bool isZip64){ m_IsZip64 = isZip64; m_ExtraSize = isZip64 ? (4 + 8 + 8) : 0; m_LocalFileHeaderSize = 4 + NFileHeader::kLocalBlockSize + fileNameLength + m_ExtraSize;}void COutArchive::PrepareWriteCompressedData(UInt16 fileNameLength, UInt64 unPackSize){ // We test it to 0xF8000000 to support case when compressed size // can be larger than uncompressed size. PrepareWriteCompressedDataZip64(fileNameLength, unPackSize >= 0xF8000000);}void COutArchive::PrepareWriteCompressedData2(UInt16 fileNameLength, UInt64 unPackSize, UInt64 packSize){ bool isUnPack64 = unPackSize >= 0xFFFFFFFF; bool isPack64 = packSize >= 0xFFFFFFFF; bool isZip64 = isPack64 || isUnPack64; PrepareWriteCompressedDataZip64(fileNameLength, isZip64);}void COutArchive::WriteBytes(const void *buffer, UInt32 size){ UInt32 processedSize; if(WriteStream(m_Stream, buffer, size, &processedSize) != S_OK) throw 0; if(processedSize != size) throw 0; m_BasePosition += size;}void COutArchive::WriteByte(Byte b){ WriteBytes(&b, 1);}void COutArchive::WriteUInt16(UInt16 value){ for (int i = 0; i < 2; i++) { WriteByte((Byte)value); value >>= 8; }}void COutArchive::WriteUInt32(UInt32 value){ for (int i = 0; i < 4; i++) { WriteByte((Byte)value); value >>= 8; }}void COutArchive::WriteUInt64(UInt64 value){ for (int i = 0; i < 8; i++) { WriteByte((Byte)value); value >>= 8; }}HRESULT COutArchive::WriteLocalHeader(const CItem &item){ m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL); bool isZip64 = m_IsZip64 || item.PackSize >= 0xFFFFFFFF || item.UnPackSize >= 0xFFFFFFFF; WriteUInt32(NSignature::kLocalFileHeader); WriteByte(item.ExtractVersion.Version); WriteByte(item.ExtractVersion.HostOS); WriteUInt16(item.Flags); WriteUInt16(item.CompressionMethod); WriteUInt32(item.Time); WriteUInt32(item.FileCRC); WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.PackSize); WriteUInt32(isZip64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize); WriteUInt16(item.Name.Length()); UInt16 localExtraSize = isZip64 ? (4 + 16): 0; if (localExtraSize > m_ExtraSize) return E_FAIL; WriteUInt16(m_ExtraSize); // test it; WriteBytes((const char *)item.Name, item.Name.Length()); if (m_ExtraSize > 0) { UInt16 remain = m_ExtraSize - 4; WriteUInt16(0x1); // Zip64 Tag; WriteUInt16(remain); if (isZip64) { WriteUInt64(item.UnPackSize); WriteUInt64(item.PackSize); remain -= 16; } for (int i = 0; i < remain; i++) WriteByte(0); } MoveBasePosition(item.PackSize); m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL); return S_OK;}void COutArchive::WriteCentralHeader(const CItem &item){ m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL); bool isUnPack64 = item.UnPackSize >= 0xFFFFFFFF; bool isPack64 = item.PackSize >= 0xFFFFFFFF; bool isPosition64 = item.LocalHeaderPosition >= 0xFFFFFFFF; bool isZip64 = isPack64 || isUnPack64 || isPosition64; WriteUInt32(NSignature::kCentralFileHeader); WriteByte(item.MadeByVersion.Version); WriteByte(item.MadeByVersion.HostOS); WriteByte(item.ExtractVersion.Version); WriteByte(item.ExtractVersion.HostOS); WriteUInt16(item.Flags); WriteUInt16(item.CompressionMethod); WriteUInt32(item.Time); WriteUInt32(item.FileCRC); WriteUInt32(isPack64 ? 0xFFFFFFFF: (UInt32)item.PackSize); WriteUInt32(isUnPack64 ? 0xFFFFFFFF: (UInt32)item.UnPackSize); WriteUInt16(item.Name.Length()); UInt16 zip64ExtraSize = (isUnPack64 ? 8: 0) + (isPack64 ? 8: 0) + (isPosition64 ? 8: 0); UInt16 centralExtraSize = isZip64 ? (4 + zip64ExtraSize) : 0; centralExtraSize += (UInt16)item.CentralExtra.GetSize(); WriteUInt16(centralExtraSize); // test it; WriteUInt16((UInt16)item.Comment.GetCapacity()); WriteUInt16(0); // DiskNumberStart; WriteUInt16(item.InternalAttributes); WriteUInt32(item.ExternalAttributes); WriteUInt32(isPosition64 ? 0xFFFFFFFF: (UInt32)item.LocalHeaderPosition); WriteBytes((const char *)item.Name, item.Name.Length()); if (isZip64) { WriteUInt16(0x1); // Zip64 Tag; WriteUInt16(zip64ExtraSize); if(isUnPack64) WriteUInt64(item.UnPackSize); if(isPack64) WriteUInt64(item.PackSize); if(isPosition64) WriteUInt64(item.LocalHeaderPosition); } if (item.CentralExtra.SubBlocks.Size() != 0) { for (int i = 0; i < item.CentralExtra.SubBlocks.Size(); i++) { CExtraSubBlock subBlock = item.CentralExtra.SubBlocks[i]; WriteUInt16(subBlock.ID); WriteUInt16((UInt16)subBlock.Data.GetCapacity()); WriteBytes(subBlock.Data, (UInt32)subBlock.Data.GetCapacity()); } } if (item.Comment.GetCapacity() > 0) WriteBytes(item.Comment, (UInt32)item.Comment.GetCapacity());}void COutArchive::WriteCentralDir(const CObjectVector<CItem> &items, const CByteBuffer &comment){ m_Stream->Seek(m_BasePosition, STREAM_SEEK_SET, NULL); UInt64 cdOffset = GetCurrentPosition(); for(int i = 0; i < items.Size(); i++) WriteCentralHeader(items[i]); UInt64 cd64EndOffset = GetCurrentPosition(); UInt64 cdSize = cd64EndOffset - cdOffset; bool cdOffset64 = cdOffset >= 0xFFFFFFFF; bool cdSize64 = cdSize >= 0xFFFFFFFF; bool items64 = items.Size() >= 0xFFFF; bool isZip64 = (cdOffset64 || cdSize64 || items64); if (isZip64) { WriteUInt32(NSignature::kZip64EndOfCentralDir); WriteUInt64(kZip64EndOfCentralDirRecordSize); // ThisDiskNumber = 0; WriteUInt16(45); // version WriteUInt16(45); // version WriteUInt32(0); // ThisDiskNumber = 0; WriteUInt32(0); // StartCentralDirectoryDiskNumber;; WriteUInt64((UInt64)items.Size()); WriteUInt64((UInt64)items.Size()); WriteUInt64((UInt64)cdSize); WriteUInt64((UInt64)cdOffset); WriteUInt32(NSignature::kZip64EndOfCentralDirLocator); WriteUInt32(0); // number of the disk with the start of the zip64 end of central directory WriteUInt64(cd64EndOffset); WriteUInt32(1); // total number of disks } WriteUInt32(NSignature::kEndOfCentralDir); WriteUInt16(0); // ThisDiskNumber = 0; WriteUInt16(0); // StartCentralDirectoryDiskNumber; WriteUInt16(items64 ? 0xFFFF: (UInt16)items.Size()); WriteUInt16(items64 ? 0xFFFF: (UInt16)items.Size()); WriteUInt32(cdSize64 ? 0xFFFFFFFF: (UInt32)cdSize); WriteUInt32(cdOffset64 ? 0xFFFFFFFF: (UInt32)cdOffset); UInt16 commentSize = (UInt16)comment.GetCapacity(); WriteUInt16(commentSize); if (commentSize > 0) WriteBytes((const Byte *)comment, commentSize);}void COutArchive::CreateStreamForCompressing(IOutStream **outStream){ COffsetOutStream *streamSpec = new COffsetOutStream; CMyComPtr<IOutStream> tempStream(streamSpec); streamSpec->Init(m_Stream, m_BasePosition + m_LocalFileHeaderSize); *outStream = tempStream.Detach();}void COutArchive::SeekToPackedDataPosition(){ m_Stream->Seek(m_BasePosition + m_LocalFileHeaderSize, STREAM_SEEK_SET, NULL);}void COutArchive::CreateStreamForCopying(ISequentialOutStream **outStream){ CMyComPtr<ISequentialOutStream> tempStream(m_Stream); *outStream = tempStream.Detach();}}}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -