예제 #1
0
        internal void WriteDir(IFormatterX writer)
        {
            Signature = ZipConstants.ZipDirEntrySignature;

            // 写入头部
            writer.Write(this);
        }
예제 #2
0
        internal void Write(IFormatterX writer)
        {
            Signature = ZipConstants.ZipEntrySignature;

            // 取得数据流位置
            RelativeOffsetOfLocalHeader = (UInt32)writer.Stream.Position;

            if (IsDirectory)
            {
                // 写入头部
                writer.Write(this);

                return;
            }

            Int32 dsLen = (Int32)DataSource.Length;

            //if (dsLen <= 0) CompressionMethod = CompressionMethod.Stored;

            // 计算签名和大小
            if (Crc == 0)
            {
                Crc = DataSource.GetCRC();
            }
            if (UncompressedSize == 0)
            {
                UncompressedSize = (UInt32)dsLen;
            }
            if (CompressionMethod == CompressionMethod.Stored)
            {
                CompressedSize = UncompressedSize;
            }
            if (DataSource.IsCompressed)
            {
                CompressedSize = (UInt32)dsLen;
            }

            // 写入头部
            writer.Write(this);

            // 没有数据,直接跳过
            if (dsLen <= 0)
            {
                return;
            }

            #region 写入文件数据
            // 数据源。只能用一次,因为GetData的时候把数据流移到了合适位置
            var source = DataSource.GetData();
            if (DataSource.IsCompressed)
            {
                // 可能数据源是曾经被压缩过了的,比如刚解压的实体
                source.CopyTo(writer.Stream, 0, dsLen);
                return;
            }

            switch (CompressionMethod)
            {
            case CompressionMethod.Stored:
                // 原始数据流直接拷贝到目标。必须指定大小,否则可能读过界
                source.CopyTo(writer.Stream, 0, dsLen);
                break;

            case CompressionMethod.Deflated:
            {
                // 记录数据流位置,待会用来计算已压缩大小
                Int64 p = writer.Stream.Position;
                using (var stream = new DeflateStream(writer.Stream, CompressionMode.Compress, true))
                {
                    source.CopyTo(stream);
                    stream.Close();
                }
                CompressedSize = (UInt32)(writer.Stream.Position - p);

                // 回头重新修正压缩后大小CompressedSize
                p = writer.Stream.Position;
                // 计算好压缩大小字段所在位置
                writer.Stream.Seek(RelativeOffsetOfLocalHeader + 18, SeekOrigin.Begin);
                //var wr = writer as IWriter2;
                //wr.Write(CompressedSize);
                writer.Write(CompressedSize);
                writer.Stream.Seek(p, SeekOrigin.Begin);
            }

            break;
            //case CompressionMethod.LZMA:
            //    {
            //        // 记录数据流位置,待会用来计算已压缩大小
            //        Int64 p = writer.Stream.Position;
            //        source.CompressLzma(writer.Stream, 10);
            //        CompressedSize = (UInt32)(writer.Stream.Position - p);

            //        // 回头重新修正压缩后大小CompressedSize
            //        p = writer.Stream.Position;
            //        // 计算好压缩大小字段所在位置
            //        writer.Stream.Seek(RelativeOffsetOfLocalHeader + 18, SeekOrigin.Begin);
            //        var wr = writer as IWriter2;
            //        wr.Write(CompressedSize);
            //        writer.Stream.Seek(p, SeekOrigin.Begin);
            //    }

            //    break;
            default:
                throw new XException("无法处理的压缩算法{0}!", CompressionMethod);
            }
            //#if DEBUG
            //            if (ts != null) ts.UseConsole = true;
            //#endif
            #endregion
        }