public void WriteFile(Stream outstream, FileInArchive file, byte[] data) { MemoryStream inputMS = new MemoryStream(data); MemoryStream outputMS = new MemoryStream(); byte[] output_buffer = new byte[0]; if (file.Descriptor.CompressionMethod == 1) //ZLib compression { ICSharpCode.SharpZipLib.Zip.Compression.Deflater def = new ICSharpCode.SharpZipLib.Zip.Compression.Deflater(); ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream defstream = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream(outputMS, def); defstream.Write(data, 0, data.Length); defstream.Flush(); defstream.Finish(); output_buffer = outputMS.GetBuffer(); file.Descriptor.UncompressedSize = (uint)inputMS.Length; Write(outstream, file, outputMS); } else if (file.Descriptor.CompressionMethod == 0) //No compression { file.Descriptor.CompressionMethod = 0; inputMS.CopyTo(outputMS); file.Descriptor.UncompressedSize = (uint)inputMS.Length; Write(outstream, file, outputMS); } }
//--------- public static byte[] Compress(byte[] input) { System.IO.MemoryStream ms = new MemoryStream(); var def = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream(ms, new ICSharpCode.SharpZipLib.Zip.Compression.Deflater(9)); def.Write(input, 0, input.Length); def.Flush(); def.Finish(); return ms.ToArray(); }
/// <summary> /// Replaces a file by a file /// </summary> /// <param name="archFile">file to replace</param> /// <param name="newFile">new file</param> public void ReplaceFile(FileInArchive archFile, FileStream newFile) { byte[] newFileBuffer = new byte[newFile.Length]; newFile.Read(newFileBuffer, 0, newFileBuffer.Length); MemoryStream inputMS = new MemoryStream(newFileBuffer); MemoryStream outputMS = new MemoryStream(); byte[] output_buffer = new byte[0]; if (archFile.descriptor.compressionMethod == 1 && false) //ZLib compression { try { ICSharpCode.SharpZipLib.Zip.Compression.Deflater def = new ICSharpCode.SharpZipLib.Zip.Compression.Deflater(); ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream defstream = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream(outputMS, def); defstream.Write(newFileBuffer, 0, newFileBuffer.Length); defstream.Flush(); defstream.Finish(); output_buffer = outputMS.GetBuffer(); } catch { } archFile.descriptor.uncompressedSize = (uint)inputMS.Length; WriteFileToArchive(archFile, outputMS); } else if (archFile.descriptor.compressionMethod == 0 || true) //No compression { archFile.descriptor.compressionMethod = 0; CopyStream(inputMS, outputMS); archFile.descriptor.uncompressedSize = (uint)inputMS.Length; WriteFileToArchive(archFile, outputMS); } }
/// <summary> /// Writes the specified dictionary as a slob file. Text is encoded as UTF8, and compression is zlib. /// </summary> /// <param name="dict">The dictionary to write.</param> /// <param name="mimeContentType">MIME content type of the values of the dictionary.</param> public void Write(Dictionary <string, string> dict, string mimeContentType) { // for format details see // https://github.com/itkach/slob KeyValuePair <string, string>[] listDict = dict.ToArray(); CompareInfo myComp_enUS = new CultureInfo("en-US", false).CompareInfo; SortKey[] sortKeys = listDict.Select(x => myComp_enUS.GetSortKey(x.Key)).ToArray(); Array.Sort(sortKeys, listDict, new UnicodeStringSorter()); using (_stream = new FileStream(_fileName, FileMode.Create, FileAccess.Write, FileShare.Read)) { System.Text.Encoding encoding = System.Text.UTF8Encoding.UTF8; BigEndianBitConverter.WriteUInt64(SupposedMagic, _stream); BigEndianBitConverter.WriteUInt64(SupposedVersionHi, _stream); BigEndianBitConverter.WriteUInt64(SupposedVersionLo, _stream); BigEndianBitConverter.WriteTinyText("utf-8", _stream, encoding); BigEndianBitConverter.WriteTinyText("zlib", _stream, encoding); // Tag count _stream.WriteByte(0); // char-sized sequence of content types _stream.WriteByte(1); // there is only one content type here BigEndianBitConverter.WriteText(mimeContentType, _stream, encoding); // Blobcount long posBlobCount = _stream.Position; BigEndianBitConverter.WriteUInt32(0, _stream); // PlaceHolder for BlobCount // Store offset long posStoreOffset = _stream.Position; BigEndianBitConverter.WriteUInt64(0, _stream); // Size long posSize = _stream.Position; BigEndianBitConverter.WriteUInt64(0, _stream); // list of long-positioned refs BigEndianBitConverter.WriteUInt32((uint)listDict.Length, _stream); long posRefTablePositions = _stream.Position; long posRefTableBegin = _stream.Position + 8 * listDict.Length; _stream.Seek(posRefTableBegin, SeekOrigin.Begin); int i = -1; int binIndex = 0; int itemIndex = 0; int contentLength = 0; List <int> listOfEntryCounts = new List <int>(); // for every store item, this list contains the number of elements stored into it foreach (KeyValuePair <string, string> entry in listDict) { ++i; // Store current stream position in refTable { long currentPos = _stream.Position; _stream.Seek(posRefTablePositions + i * 8, SeekOrigin.Begin); BigEndianBitConverter.WriteUInt64((ulong)(currentPos - posRefTableBegin), _stream); _stream.Seek(currentPos, SeekOrigin.Begin); } BigEndianBitConverter.WriteText(entry.Key, _stream, encoding); BigEndianBitConverter.WriteUInt32((uint)binIndex, _stream); BigEndianBitConverter.WriteUInt16((ushort)itemIndex, _stream); BigEndianBitConverter.WriteTinyText(string.Empty, _stream, encoding); ++itemIndex; contentLength += entry.Value.Length; if (itemIndex >= 32768 || contentLength > 320 * 1024) // limit one store item to 32767 entries or a maximum length of 320 kB { listOfEntryCounts.Add(itemIndex); contentLength = 0; itemIndex = 0; ++binIndex; } } if (itemIndex != 0) { listOfEntryCounts.Add(itemIndex); } // Write the blob count and store offset { long currentPos = _stream.Position; _stream.Seek(posBlobCount, SeekOrigin.Begin); BigEndianBitConverter.WriteUInt32((uint)listOfEntryCounts.Count, _stream); // Blob-Count // Write the store offset BigEndianBitConverter.WriteUInt64((ulong)currentPos, _stream); _stream.Seek(currentPos, SeekOrigin.Begin); } // list of long-positioned store items BigEndianBitConverter.WriteUInt32((uint)listOfEntryCounts.Count, _stream); // Store count long posStoreOffsetTable = _stream.Position; _stream.Seek(posStoreOffsetTable + 8 * listOfEntryCounts.Count, SeekOrigin.Begin); long posStoreBegin = _stream.Position; int itemIndexOffset = 0; for (binIndex = 0; binIndex < listOfEntryCounts.Count; ++binIndex) { { long currentPos = _stream.Position; _stream.Seek(posStoreOffsetTable + 8 * binIndex, SeekOrigin.Begin); BigEndianBitConverter.WriteUInt64((ulong)(currentPos - posStoreBegin), _stream); _stream.Seek(currentPos, SeekOrigin.Begin); } BigEndianBitConverter.WriteUInt32((uint)listOfEntryCounts[binIndex], _stream); for (int j = 0; j < listOfEntryCounts[binIndex]; ++j) { _stream.WriteByte(0); // Table with content ids } long posContentLength = _stream.Position; BigEndianBitConverter.WriteUInt32(0, _stream); // Placeholder for content length // compressStream = new System.IO.Compression.DeflateStream(_stream, System.IO.Compression.CompressionLevel.Optimal, true); using (ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream compressStream = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream(_stream, new ICSharpCode.SharpZipLib.Zip.Compression.Deflater(), 1024 * 1024) { IsStreamOwner = false }) { // now write the content // First list of item offsets (without count) int itemPositionOffset = 0; for (int k = 0; k < listOfEntryCounts[binIndex]; ++k) { BigEndianBitConverter.WriteUInt32((uint)itemPositionOffset, compressStream); itemPositionOffset += 4 + encoding.GetByteCount(listDict[itemIndexOffset + k].Value); } // now the content itself for (int k = 0; k < listOfEntryCounts[binIndex]; ++k) { BigEndianBitConverter.WriteBigText(listDict[itemIndexOffset + k].Value, compressStream, encoding); } itemIndexOffset += listOfEntryCounts[binIndex]; compressStream.Flush(); compressStream.Close(); } { // Write content length long currentPosition = _stream.Position; _stream.Seek(posContentLength, SeekOrigin.Begin); BigEndianBitConverter.WriteUInt32((uint)(currentPosition - posContentLength - 4), _stream); _stream.Seek(currentPosition, SeekOrigin.Begin); } } } }
/// <summary> /// Replaces a file by a file /// </summary> /// <param name="archFile">file to replace</param> /// <param name="newFile">new file</param> public void ReplaceFile(FileInArchive archFile, FileStream newFile) { byte[] newFileBuffer = new byte[newFile.Length]; newFile.Read(newFileBuffer, 0, newFileBuffer.Length); MemoryStream inputMS = new MemoryStream(newFileBuffer); MemoryStream outputMS = new MemoryStream(); byte[] output_buffer = new byte[0]; if (archFile.descriptor.compressionMethod == 1 && false) //ZLib compression { try { ICSharpCode.SharpZipLib.Zip.Compression.Deflater def = new ICSharpCode.SharpZipLib.Zip.Compression.Deflater(); ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream defstream = new ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream(outputMS, def); defstream.Write(newFileBuffer, 0, newFileBuffer.Length); defstream.Flush(); defstream.Finish(); output_buffer = outputMS.GetBuffer(); } catch (Exception) { } archFile.descriptor.uncompressedSize = (uint)inputMS.Length; WriteFileToArchive(archFile, outputMS); } else if (archFile.descriptor.compressionMethod == 0 || true) //No compression { archFile.descriptor.compressionMethod = 0; CopyStream(inputMS, outputMS); archFile.descriptor.uncompressedSize = (uint)inputMS.Length; WriteFileToArchive(archFile, outputMS); } }