/// <summary> /// 展開準備 /// prepare to inflate /// </summary> public void Prepare(byte[] data) { _stream = new MemoryStream(data); //ヘッダ読み取り //read szip header { var binStream = new BinaryReader(_stream); _header = new SZipHeader(); _header.Read(binStream); } //各コンテンツ情報読み取り //read each content information { //要素情報テーブル解凍 _stream.Seek(SZipHeader.Size, SeekOrigin.Begin); var decompressed = SZipUtility.ZlibDecompress(_stream, SZipContent.Size * _header.ContentCount, _header.CompressedContentHeaderTableSize); _contents = new SZipContent[_header.ContentCount]; using (MemoryStream stream = new MemoryStream(decompressed)) { for (int contentIndex = 0; contentIndex < _header.ContentCount; contentIndex++) { var content = new SZipContent(); content.Read(new BinaryReader(stream)); _contents[contentIndex] = content; } } } //要素名読み取り //read each content name { //要素名前テーブル解凍 _stream.Seek(SZipHeader.Size + _header.CompressedContentHeaderTableSize, SeekOrigin.Begin); var decompressed = SZipUtility.ZlibDecompress(_stream, (int)_header.OriginalContentNameTableSize, (int)_header.CompressedContentNameTableSize); _fileNameTable = new string[_header.ContentCount]; _contentNameHashSet = new HashSet <string>(); using (MemoryStream fnameStream = new MemoryStream(decompressed)) { using (BinaryReader binReader = new BinaryReader(fnameStream)) { for (int contentIndex = 0; contentIndex < _header.ContentCount; contentIndex++) { int length = (int)_contents[contentIndex].NameByteSize; var from = binReader.ReadBytes(length); var contentName = System.Text.Encoding.UTF8.GetString(from); _fileNameTable[contentIndex] = contentName; } } } } }
/// <summary> /// 圧縮 /// </summary> public byte[] Deflate() { //データ部圧縮 //compress datas List <int> originalContentDataSizeTable = new List <int>(); List <byte[]> compressedContentDataTable = new List <byte[]>(_contentFileInfoTable.Count); int compressedContentDataTableSize = 0; for (int contentIndex = 0; contentIndex < _contentFileInfoTable.Count; contentIndex++) { var fileInfo = _contentFileInfoTable[contentIndex]; var data = System.IO.File.ReadAllBytes(fileInfo.FullName); originalContentDataSizeTable.Add(data.Length); var compressed = ZlibStream.CompressBuffer(data); compressedContentDataTableSize += compressed.Length; compressedContentDataTable.Add(compressed); } //ファイル名部圧縮 //compress name table byte[] compressedContentNameTable = null; int compressedContentNameTableSize = 0; { //全ファイル名結合 System.Text.StringBuilder builder = new System.Text.StringBuilder(); foreach (var s in _contentNameTable) { builder.Append(s); compressedContentNameTableSize += System.Text.Encoding.UTF8.GetByteCount(s); } compressedContentNameTable = ZlibStream.CompressString(builder.ToString()); } //コンテンツ情報部圧縮 //compress contents byte[] compressedContentTable = null; { byte[] headerTable = new byte[SZipContent.Size * _contentFileInfoTable.Count]; using (MemoryStream stream = new MemoryStream(headerTable)) { using (BinaryWriter writer = new BinaryWriter(stream)) { for (int contentIndex = 0; contentIndex < _contentFileInfoTable.Count; contentIndex++) { var content = new SZipContent(); System.UInt32 crc = SZipUtility.FNVHash(compressedContentDataTable[contentIndex]); content.Set(_contentNameTable[contentIndex].Length, originalContentDataSizeTable[contentIndex], compressedContentDataTable[contentIndex].Length, crc); content.Write(writer); } } } compressedContentTable = ZlibStream.CompressBuffer(headerTable); } //ヘッダ生成 //create szip header var header = new SZipHeader(); header.Set((System.Int16)_contentFileInfoTable.Count, SZipUtility.FNVHash(compressedContentNameTable), SZipUtility.FNVHash(compressedContentTable), compressedContentTable.Length, compressedContentNameTableSize, compressedContentNameTable.Length); //書き込み //write to byte[] { int totalSize = SZipHeader.Size + compressedContentTable.Length + compressedContentNameTable.Length + compressedContentDataTableSize; byte[] output = new byte[totalSize]; using (MemoryStream stream = new MemoryStream(output)) { using (BinaryWriter writer = new BinaryWriter(stream)) { //ヘッダ header.Write(writer); //コンテンツ writer.Write(compressedContentTable); //コンテンツ名 writer.Write(compressedContentNameTable); //データ foreach (var data in compressedContentDataTable) { writer.Write(data); } } } return(output); } }