/// <summary> /// Writes the header of the file with the writer. /// </summary> /// <param name="writer"> The writer. </param> /// <param name="entry"> The entry. </param> /// <param name="isCentralFileHeader"> Determines whether header is central file header or not (local). </param> private void WriteFileHeader(IByteArrayWriter writer, ZipWriteOnlyStorerEntry entry, bool isCentralFileHeader) { if (isCentralFileHeader) { writer.WriteBytes(centralDirectoryFileHeaderSignatureBytes); // 4 bytes, central directory file header signature writer.WriteBytes(23, 0xB); // 2 bytes, version made by } else { writer.WriteBytes(localFileHeaderSignatureBytes); // 4 bytes, local file header signature } writer.WriteBytes(versionToExtractBytes); // 2 bytes, version needed to extract (minimum) writer.WriteBytes(gpbg8Bytes); // 2 bytes, general purpose bit flag writer.WriteBytes(entry.CompressionMethodAsBytes); // 2 bytes, compression method writer.WriteBytes(entry.ModifyTimeAsBytes); // 2+2 bytes, file last modification time and date writer.WriteBytes(entry.CRC32AsBytes); // 4 bytes, CRC-32 writer.WriteBytes(entry.CompressedSizeAsBytes); // 4 bytes, compressed size writer.WriteBytes(entry.SizeAsBytes); // 4 bytes, uncompressed size writer.WriteBytes(entry.PathLengthAsBytes); // 2 bytes, file name length if (this.isZip64) { writer.WriteBytes(thirtyTwo2Bytes); // 2 bytes, extra field length = 32 } else { writer.WriteBytes(zero2Bytes); // 2 bytes, extra field length = 32 } if (isCentralFileHeader) { writer.WriteBytes(entry.CommentLengthAsBytes); // 2 bytes, file comment length writer.WriteBytes(zero4Bytes); // 2+2=4 bytes, disk number where file starts (disk=0), internal file attributes writer.WriteBytes(externalAttributesBytes); // 4 bytes, External file attributes writer.WriteBytes(entry.HeaderOffsetAsBytes); // 4 bytes, relative offset of header } writer.WriteBytes(entry.PathAsBytes); // variable size, file name if (this.isZip64) { writer.WriteBytes(zip64ExtraBlockTagSignatureBytes); // 2 bytes, tag for the extra block (ZIP64 Extended Information Extra Field) writer.WriteBytes(thirtyTwo2Bytes); // 2 bytes, size of the extra block writer.WriteBytes(zero4Bytes); writer.WriteBytes(entry.SizeZip64AsBytes); // 8 bytes, uncompressed size writer.WriteBytes(zero4Bytes); writer.WriteBytes(entry.CompressedSizeZip64AsBytes); // 8 bytes, compressed size writer.WriteBytes(zero4Bytes); writer.WriteBytes(entry.HeaderOffsetZip64AsBytes); // 8 bytes, compressed size writer.WriteBytes(zero4Bytes); // 4 bytes, disk number where file starts (disk=0) } if (isCentralFileHeader) { writer.WriteBytes(entry.CommentAsBytes); // variable size, file comment } }
/// <inheritdoc/> public IDataStorerEntry Add(string path, params byte[] data) { Validation.NotNull("Path", path); Validation.NotNull("Data", data); string normalizedPath = path.Replace('\\', '/'); int pos = normalizedPath.IndexOf(':'); if (pos >= 0) { normalizedPath = normalizedPath.Remove(0, pos + 1); } normalizedPath = normalizedPath.Trim('/'); int uncompressedLength = data.Length; int compressedLength; byte[] compressedData; CompressionMethod compressionMethod; if (this.enableCompression) { Deflater deflater = new Deflater(Deflater.DEFLATED); deflater.SetInput(data, 0, uncompressedLength); deflater.Finish(); compressedData = new byte[uncompressedLength]; compressedLength = deflater.Deflate(compressedData, 0, uncompressedLength); if (deflater.IsFinished && compressedLength <= uncompressedLength) { // Use deflate compressionMethod = CompressionMethod.Deflate; } else { // Force to store compressedData = data; compressedLength = uncompressedLength; compressionMethod = CompressionMethod.Store; } } else { // Only store compressedData = data; compressedLength = uncompressedLength; compressionMethod = CompressionMethod.Store; } uint uncompressedSize = (uint)uncompressedLength; uint compressedSize = (uint)compressedLength; uint crc32 = CRC32.Calculate(data); uint headerOffset = (uint)this.zipFileWriter.Position; ZipWriteOnlyStorerEntry fileEntry = new ZipWriteOnlyStorerEntry( normalizedPath, uncompressedSize, compressionMethod, compressedSize, headerOffset, crc32, DateTime.Now, comment ?? "" ); this.WriteFileHeader(this.zipFileWriter, fileEntry, false); this.zipFileWriter.WriteBytes(compressedData, 0, compressedLength); this.entries.AddLast(fileEntry); return(fileEntry); }