Provides a writable stream that uses ZLIB algorithm to either compresses or decompresses data written to it and saves the resulting data blocks into an underlying stream. Unlike similar class present in .NET Framework 2.0, this one actually makes it possible to use Flush when compressing data to make sure all data written to the stream have been written into the underlying stream as well.
상속: Stream
예제 #1
0
        private CompressionType xBoxUncompress(string compFilename, string uncompFilename)
        {
            if (uncompFilename.ToLower() == compFilename.ToLower()) //nothing to do
                return CompressionType.None;

            if (File.Exists(uncompFilename))
                File.Delete(uncompFilename);

            CompressionType ct = CompressionType.None;

            try
            {
                using (FileStream inFileStream = new FileStream(compFilename, FileMode.Open, FileAccess.Read))
                {
                    using (BinaryEndianReader br = new BinaryEndianReader(inFileStream))
                    {
                        uint chunkLen = 0;

                        while (chunkLen != 0xffffffff)
                        {
                            using (FileStream outFileStream = new FileStream(uncompFilename, chunkLen == 0 ? FileMode.Create : FileMode.Append))
                            {
                                using (ZlibOutputStream outZStream = new ZlibOutputStream(outFileStream, Rebex.IO.Compression.CompressionMode.Decompress))
                                {
                                    //test for newer GHWT+ compression
                                    long pos = inFileStream.Position;

                                    if (Encoding.ASCII.GetString(br.ReadBytes(4)) == "CHNK")
                                    {
                                        ct = CompressionType.ZLibChunk;

                                        EndianType et = this.EndianType;

                                        //Decompress each section
                                        uint headerLen = br.ReadUInt32(et);
                                        uint blockLen = br.ReadUInt32(et);
                                        chunkLen = br.ReadUInt32(et);
                                        uint nextchunkLen = br.ReadUInt32(et);
                                        uint uncompressedLen = br.ReadUInt32(et);
                                        uint uncompressedPos = br.ReadUInt32(et);

                                        _zLibHeaderLen = headerLen;
                                        if (uncompressedLen > this._zLibChunkSize)
                                            this._zLibChunkSize = uncompressedLen;

                                        inFileStream.Seek(headerLen - (inFileStream.Position - pos), SeekOrigin.Current);
                                        outZStream.WriteByte(0x58);  //Search deflate.cs for "Nanook" for the mod to stop it being written out
                                        outZStream.WriteByte(0x85);  //this is the header MS uses, thie zlib deflate uses 78DA ??

                                        copyStream(inFileStream, outZStream, (int)blockLen);

                                        if (chunkLen != 0xffffffff)
                                            inFileStream.Seek((chunkLen - blockLen) - headerLen, SeekOrigin.Current);

                                    }
                                    else
                                    {
                                        try
                                        {
                                            inFileStream.Seek(pos, SeekOrigin.Begin);

                                            outZStream.WriteByte(0x58);
                                            outZStream.WriteByte(0x85);
                                            copyStream(inFileStream, outZStream);
                                            ct = CompressionType.ZLib;
                                            break;
                                        }
                                        catch
                                        {
                                            break;  //no compression???
                                        }
                                    }

                                    outZStream.Flush();
                                    outFileStream.Flush();
                                    //outZStream.Close();
                                }
                            }
                        }
                    }
                }
            }
            catch (Exception ex)
            {
                throw new ApplicationException(string.Format("Uncompress Failed: {0}", ex));
            }

            //using (DeflateStream ds = new DeflateStream(File.Open(compFilename, FileMode.Open), CompressionMode.Decompress))
            //{
            //    using (BinaryReader br = new BinaryReader(ds))
            //    {
            //        using (FileStream ms = File.Create(uncompFilename))
            //        {
            //            using (BinaryWriter bw = new BinaryWriter(ms))
            //            {
            //                long l;
            //                do
            //                {
            //                    l = ms.Length;
            //                    bw.Write(br.ReadBytes(10000));
            //                }
            //                while (l != ms.Length);
            //            }
            //        }
            //    }
            //}

            return ct;
        }
예제 #2
0
        private void xBoxCompress(string uncompFilename, string compFilename)
        {
            if (uncompFilename.ToLower() == compFilename.ToLower()) //nothing to do
                return;

            if (File.Exists(compFilename))
                File.Delete(compFilename);

            try
            {
                if (this.CompressionType == CompressionType.ZLib)
                {
                    using (FileStream outFileStream = new FileStream(compFilename, FileMode.Create))
                    {
                        using (ZlibOutputStream outZStream = new ZlibOutputStream(outFileStream, true, JZlib.Z_BEST_COMPRESSION))
                        {
                            using (FileStream inFileStream = new FileStream(uncompFilename, FileMode.Open, FileAccess.Read))
                            {
                                copyStream(inFileStream, outZStream);
                            }
                        }
                    }
                }
                else if (this.CompressionType == CompressionType.ZLibChunk)
                {
                    List<uint> sizes = new List<uint>();
                    List<uint> offsets = new List<uint>();
                    byte[] header = new byte[ZlibFilePad];

                    int pad = 0;
                    long lastUncompressedChunk;
                    long endPos;

                    EndianType et = this.EndianType;

                    int part = 0;

                    using (FileStream inFileStream = new FileStream(uncompFilename, FileMode.Open, FileAccess.Read))
                    {
                        long pos;
                        do
                        {
                            using (FileStream outFileStream = new FileStream(compFilename, inFileStream.Position == 0 ? FileMode.Create : FileMode.Append))
                            {
                                part++;

                                pad = (int)(outFileStream.Position % ZlibBlockPad);
                                if (pad != 0 && outFileStream.Position != 0)
                                    outFileStream.Write(header, 0, (int)ZlibBlockPad - pad);

                                pos = outFileStream.Position;

                                outFileStream.Write(Encoding.ASCII.GetBytes("CHNK"), 0, 4);
                                outFileStream.Write(header, 0, (int)_zLibHeaderLen - 4);

                                lastUncompressedChunk = (long)_zLibChunkSize;
                                if (inFileStream.Position + lastUncompressedChunk > inFileStream.Length)
                                    lastUncompressedChunk = inFileStream.Length - inFileStream.Position;

                                using (ZlibOutputStream outZStream = new ZlibOutputStream(outFileStream, true, JZlib.Z_BEST_COMPRESSION))
                                {
                                    copyStream(inFileStream, outZStream, (int)lastUncompressedChunk);

                                    offsets.Add((uint)pos);
                                    sizes.Add((uint)(outFileStream.Position - pos) - _zLibHeaderLen);
                                }

                            }

                        } while (inFileStream.Position < inFileStream.Length);

                        using (FileStream outFileStream = new FileStream(compFilename, inFileStream.Position == 0 ? FileMode.Create : FileMode.Append))
                        {
                            //find the end of the last file.
                            endPos = (int)(outFileStream.Position % ZlibBlockPad);
                            if (endPos != 0)
                                endPos = ZlibBlockPad - endPos;
                            endPos += outFileStream.Position;

                            //pad the compressed file
                            pad = (int)(outFileStream.Position % ZlibFilePad);
                            if (pad != 0 && outFileStream.Position != 0)
                                outFileStream.Write(header, 0, (int)ZlibFilePad - pad);
                        }

                        using (FileStream outFileStream = new FileStream(compFilename, FileMode.Open))
                        {
                            using (BinaryEndianWriter bw = new BinaryEndianWriter(outFileStream))
                            {
                                long uncompressedTotal = 0;
                                EndianType e = this.EndianType;

                                for (int i = 0; i < offsets.Count; i++)
                                {
                                    outFileStream.Seek(offsets[i] + 4, SeekOrigin.Begin);
                                    bw.Write((uint)_zLibHeaderLen, e); //headerlen
                                    bw.Write((uint)sizes[i], e); //blocklen
                                    bw.Write((uint)(i != offsets.Count - 1 ? offsets[i + 1] - offsets[i] : 0xffffffff), e); //chunklen ffs if last item

                                    //next blocklen 00's if last block
                                    if (i == offsets.Count - 1)  //last item
                                        bw.Write((uint)0x00000000, e);
                                    else if (i + 1 == offsets.Count - 1) //secondlast item
                                        bw.Write((uint)(endPos - offsets[i + 1]), e);
                                    else
                                        bw.Write((uint)offsets[i + 2] - offsets[i + 1], e);

                                    bw.Write((uint)(i != offsets.Count - 1 ? _zLibChunkSize : lastUncompressedChunk), e); //uncompressed size
                                    bw.Write((uint)uncompressedTotal, e);
                                    uncompressedTotal += (i != offsets.Count - 1 ? _zLibChunkSize : lastUncompressedChunk);
                                }
                            }
                        }

                    }
                }
            }
            catch (Exception ex)
            {
                throw new ApplicationException(string.Format("Compress Failed: {0}", ex));
            }

            //using (FileStream sf = File.OpenRead(uncompFilename))
            //{
            //    using (FileStream df = File.Create(compFilename))
            //    {
            //        using (DeflateStream ds = new DeflateStream(df, CompressionMode.Compress))
            //        {
            //            byte[] b = new byte[10000];
            //            int c = 0;
            //            do
            //            {
            //                c = sf.Read(b, 0, b.Length);
            //                ds.Write(b, 0, c);
            //            }
            //            while (c == b.Length);
            //        }
            //    }
            //}
        }