Beispiel #1
0
        private void loadFromStream(Stream stream, string expectedContentType)
        {
            // TODO 流式读取尚未完成
            // 增加参数,是否一次性读取
            // 增加迭代器,用于流读取
            // 如果是流读取,只有读取结束之时,才可以使用 Nodes 属性
            var br = new BinaryReader(stream);

            if (!br.ReadBytes(5).SequenceEqual(mHeaderBytes)) // 文件头
                throw new InvalidDataException("指定的流不是 CPK 数据,或流位置不正确。");

            if ((this.FormatVersion = br.ReadUInt16()) > FORMAT_VERSION_CODE) // 版本号
                throw new NotSupportedException("不支持读取此版本的 CPK 数据(CPK 格式版本过高)");

            this.Flags = (CPKFlags)br.ReadUInt32(); // 标记位

            this.ContentType = CPKNode.readStringWithLength(br); // 正文类型

            if (expectedContentType != null && expectedContentType != this.ContentType)
                throw new InvalidDataException("输入数据的类型不是需要的类型。");

            if ((this.Flags & CPKFlags.LZ4Compressed) == CPKFlags.LZ4Compressed) {
                stream = new Ceeji.Data.Codec.LZ4.LZ4Stream(stream, System.IO.Compression.CompressionMode.Decompress, false, 1024 * 1024 * 30);
            }
            if ((this.Flags & CPKFlags.LZ4HCCompressed) == CPKFlags.LZ4HCCompressed) {
                stream = new Ceeji.Data.Codec.LZ4.LZ4Stream(stream, System.IO.Compression.CompressionMode.Decompress, true, 1024 * 1024 * 30);
            }
            if ((this.Flags & CPKFlags.DeflateCompressed) == CPKFlags.DeflateCompressed) {
                stream = new DeflateStream(stream, System.IO.Compression.CompressionMode.Decompress, true);
            }

            long pos = -1, pos2 = -1;
            if (this.HashIncluded) {
                pos = stream.Position;
            }

            CPKNode hashNode = null;

            CPKNode node;
            while ((node = CPKNode.DeserializeFromStream(stream)) != null) {
                if (node.Name != "_!#hash#!_") {
                    if (this.HashIncluded) {
                        pos2 = stream.Position;
                    }
                    this.Nodes.Add(node.Name, node);
                    if (node.Name == "_!#guid#!_") {
                        this.PackageGuid = (Guid)node.Value.Value;
                    }
                }
                else {
                    hashNode = node;
                }
            }

            if (this.HashIncluded) {
                stream.Position = pos;
                var hash = HashHelper.ComputeRawHash(new PartialReadOnlyStream(stream, pos, pos2 - pos), HashHelper.MD5Algorithm);

                if (hashNode == null || !hashNode.Get<byte[]>().SequenceEqual(hash)) {
                    throw new InvalidDataException("指定的输入数据的数据摘要不一致,可能已经被无意间修改");
                }
            }
        }
Beispiel #2
0
        /// <summary>
        /// 将包的内容写入指定的流。
        /// </summary>
        /// <param name="stream"></param>
        public void WriteToStream(Stream stream)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");

            // 打开流进行写入
            var bw = new BinaryWriter(stream);

            // 输出文件头
            bw.Write(mHeaderBytes);
            bw.Write(FORMAT_VERSION_CODE);
            bw.Write((uint)this.Flags);
            bw.Write(CPKNode.getBinaryWithLength(Encoding.UTF8.GetBytes(ContentType)));

            // 输出正文
            long pos = -1;
            if (this.HashIncluded) {
                pos = stream.Position;
            }

            if ((this.Flags & CPKFlags.LZ4Compressed) == CPKFlags.LZ4Compressed) {
                stream.Flush();
                stream = new Ceeji.Data.Codec.LZ4.LZ4Stream(stream, System.IO.Compression.CompressionMode.Compress, false, 1024 * 1024 * 30);
                bw = new BinaryWriter(stream);
            }
            if ((this.Flags & CPKFlags.LZ4HCCompressed) == CPKFlags.LZ4HCCompressed) {
                stream.Flush();
                stream = new Ceeji.Data.Codec.LZ4.LZ4Stream(stream, System.IO.Compression.CompressionMode.Compress, true, 1024 * 1024 * 30);
                bw = new BinaryWriter(stream);
            }
            if ((this.Flags & CPKFlags.DeflateCompressed) == CPKFlags.DeflateCompressed) {
                stream.Flush();
                stream = new DeflateStream(stream, System.IO.Compression.CompressionMode.Compress, true);
                bw = new BinaryWriter(stream);
            }

            // var binNodes = mEmptyByteArr;
            foreach (var node in this.Nodes) {
                if (node.Key == "_!#hash#!_")
                    continue;

                node.Value.SerializeToStream(stream);
                //binNodes = binNodes.Concat(data).ToArray();
            }

            // bw.Write(binNodes);

            // 如果需要哈希,则计算哈希
            if (this.HashIncluded) {
                long posn = stream.Position;
                stream.Position = pos;
                var hash = HashHelper.ComputeRawHash(stream, HashHelper.MD5Algorithm);
                stream.Position = posn;
                new CPKNode("_!#hash#!_", hash).SerializeToStream(stream);
            }

            // 输出结束符
            bw.Write((byte)0);
            bw.Flush();
            stream.Flush();
        }