public void PackFiles(Stream strm, List<PackFileEntry> filesToPack, Callbacks callbacks) { BinaryWriter bw = new BinaryWriter(strm); Int32 FileOffset; bw.Write(new char[] { 'Y', 'P', 'A', 'C' }); bw.Write((Int32)1); bw.Write((Int32)filesToPack.Count); bw.Write((Int32)0); // write the directory FileOffset = 16 + 7 * 16 * filesToPack.Count; // this will be the offset for the first file for (int i = 0; i < filesToPack.Count; i++) { string targetFileName = "\\" + filesToPack[i]; byte[] nameBuf = new byte[6 * 16]; Int64 Length; Encoding.ASCII.GetBytes(targetFileName, 0, targetFileName.Length, nameBuf, 0); bw.Write(nameBuf); bw.Write((Int64)FileOffset); Length = filesToPack[i].fileSize; bw.Write((Int64)Length); FileOffset += (Int32)Length; } // write the actual file data for (int i = 0; i < filesToPack.Count; i++) { byte[] fileData = callbacks.ReadData(filesToPack[i].relativePathName); strm.Write(fileData, 0, fileData.Length); } }
public void PackFiles(Stream strm, List<PackFileEntry> filesToPack, Callbacks callbacks) { SetupZIPParams(); using (ZipOutputStream zstrm = new ZipOutputStream(strm, false)) { // always use multithreaded compression zstrm.ParallelDeflateThreshold = 0; foreach (PackFileEntry pfe in filesToPack) { zstrm.PutNextEntry(pfe.relativePathName); byte[] data = callbacks.ReadData(pfe.relativePathName); zstrm.Write(data, 0, data.Length); } } // stream is closed automatically }
public void PackFiles(Stream strm, List<PackFileEntry> filesToPack, Callbacks callbacks) { int NumFiles = filesToPack.Count; BinaryWriter bw = new BinaryWriter(strm); uint id; bool compressed; uint CurrentOffset; int CompressedLength = 0; IDataTransformer compressor = callbacks.TransformerRegistry.GetTransformer("zlib_cmp"); bw.Write(grar_magic); bw.Write(NumFiles); // first pass, write "pseudo-uncompressed" file headers for (int i = 0; i < NumFiles; i++) { string fn = Path.GetFileNameWithoutExtension(filesToPack[i].relativePathName); if (!fn.StartsWith("0x")) throw new Exception(String.Format("Invalid filename '{0}', must start with hex id!", fn)); id = UInt32.Parse(fn.Substring(2, 8), System.Globalization.NumberStyles.AllowHexSpecifier); bw.Write(id); bw.Write((UInt32)0); // offset not yet defined bw.Write((UInt32)0); // compressed length bw.Write((UInt32)filesToPack[i].fileSize); } CurrentOffset = (UInt32)strm.Position; // second pass, actually write the files, compressing them on demand for (int i = 0; i < NumFiles; i++) { // first, check if file is to be compressed string fn = Path.GetFileNameWithoutExtension(filesToPack[i].relativePathName); compressed = fn.EndsWith("P"); // read the file and optionally compress it byte[] buffer = callbacks.ReadData(filesToPack[i].relativePathName); if (compressed) { byte[] buffer2 = new byte[buffer.Length + 256]; CompressedLength = buffer2.Length; compressor.TransformData(buffer, buffer2, buffer.Length, ref CompressedLength); buffer = buffer2; } else { CompressedLength = 0; } strm.Seek(8 + i * 16, SeekOrigin.Begin); // header = 8 bytes, 16 bytes per entry strm.Seek(4, SeekOrigin.Current); // skip ID bw.Write(CurrentOffset); if (compressed) bw.Write(CompressedLength + 4); // finally write the file data strm.Seek(CurrentOffset, SeekOrigin.Begin); // compressed files specify the uncompressed size again here if (compressed) { bw.Write((UInt32)filesToPack[i].fileSize); strm.Write(buffer, 0, CompressedLength); } else { strm.Write(buffer, 0, buffer.Length); } CurrentOffset = (uint)strm.Position; } }