예제 #1
0
        public PackagedFileInfo WriteFile(AbstractFileInfo info)
        {
            // Assume that all files are written uncompressed (worst-case) when calculating package sizes
            uint size = info.Size();

            if (_streams.Last().Position + size > MaxPackageSize)
            {
                // Start a new package file if the current one is full.
                string partPath = Package.MakePartFilename(_path, _streams.Count);
                var    nextPart = File.Open(partPath, FileMode.Create, FileAccess.Write);
                _streams.Add(nextPart);
            }

            Stream stream   = _streams.Last();
            var    packaged = new PackagedFileInfo
            {
                PackageStream    = stream,
                Name             = info.Name,
                UncompressedSize = size,
                ArchivePart      = (UInt32)(_streams.Count - 1),
                OffsetInFile     = (UInt32)stream.Position,
                Flags            = BinUtils.MakeCompressionFlags(Compression, CompressionLevel)
            };

            Stream packagedStream = info.MakeStream();

            byte[] compressed;
            try
            {
                using (var reader = new BinaryReader(packagedStream, Encoding.UTF8, true))
                {
                    byte[] uncompressed = reader.ReadBytes((int)reader.BaseStream.Length);
                    compressed = BinUtils.Compress(uncompressed, Compression, CompressionLevel);
                    stream.Write(compressed, 0, compressed.Length);
                }
            }
            finally
            {
                info.ReleaseStream();
            }

            packaged.SizeOnDisk = (UInt32)(stream.Position - packaged.OffsetInFile);
            packaged.Crc        = Crc32.Compute(compressed, 0);

            int padLength = PaddingLength();

            if (stream.Position % padLength <= 0)
            {
                return(packaged);
            }

            if ((_package.Metadata.Flags & PackageFlags.Solid) == 0)
            {
                // Pad the file to a multiple of 64 bytes
                var pad = new byte[padLength - stream.Position % padLength];
                for (var i = 0; i < pad.Length; i++)
                {
                    pad[i] = 0xAD;
                }

                stream.Write(pad, 0, pad.Length);
            }

            return(packaged);
        }