コード例 #1
0
        // encodes `text` and writes to `filename`, returns compression info
        public static CompressionInfo Encode(string text, string filename)
        {
            BinaryWriter writer;

            try
            {
                writer = new BinaryWriter(File.Open(filename, FileMode.Create));
            }
            catch
            {
                throw;
            }

            if (text.Length == 0)
            {
                // create an empty file
                writer.Close();
                return(new CompressionInfo(0, 0, 0, 0));
            }

            // 0. generate the tree and the code table

            HuffmanTree      tree      = HuffmanTree.GenerateHuffmanTree(text);
            HuffmanCodeTable codeTable = new HuffmanCodeTable(tree);

            // 1. encode

            // 1.1. encode the tree

            ushort[] treeBuffer      = new ushort[codeTable.NumberOfCodes * 2];
            int      treeBitPosition = 0;

            EncodeTree(tree, treeBuffer, ref treeBitPosition);

            int  treeLengthInBytes    = treeBitPosition / 8;
            byte bitsOfLastByteOfTree = (byte)(treeBitPosition % 8);

            if (bitsOfLastByteOfTree == 0)
            {
                bitsOfLastByteOfTree = 8;
            }
            else
            {
                treeLengthInBytes++;
            }

            // 1.2. encode the text

            char[]   textCharArray          = text.ToCharArray();
            ushort[] encodedTextBuffer      = new ushort[textCharArray.Length];
            long     encodedTextBitPosition = 0;

            for (int i = 0; i < textCharArray.Length; i++)
            {
                AppendCode(encodedTextBuffer, codeTable.GetHuffmanCode(textCharArray[i]), ref encodedTextBitPosition);
            }

            textCharArray = null;

            int  encodedTextLengthInBytes    = (int)(encodedTextBitPosition / 8);
            byte bitsOfLastByteOfEncodedText = (byte)(encodedTextBitPosition % 8);

            if (bitsOfLastByteOfEncodedText == 0)
            {
                bitsOfLastByteOfEncodedText = 8;
            }
            else
            {
                encodedTextLengthInBytes++;
            }

            // 2. write

            try
            {
                // 2.1. write the metadata

                // first 6 bits of the file is for FileFormatVersion,
                // next 18 bits for treeLengthInBytes,
                // next 4 bits for bitsOfLastByteOfTree,
                // next 4 bits for bitsOfLastByteOfEncodedText
                // (4 bytes for metadata in total)
                writer.Write((byte)((FileFormatVersion << 2) | (treeLengthInBytes >> 16)));
                writer.Write((byte)(treeLengthInBytes >> 8));
                writer.Write((byte)(treeLengthInBytes));
                writer.Write((byte)((bitsOfLastByteOfTree << 4) | bitsOfLastByteOfEncodedText));

                // 2.2. write the encoded tree
                WriteBuffer(writer, treeBuffer, treeBitPosition);

                // 2.3. write the encoded text
                WriteBuffer(writer, encodedTextBuffer, encodedTextBitPosition);
            }
            catch
            {
                throw;
            }
            finally
            {
                writer.Close();
            }

            return(new CompressionInfo(text.Length, 4, treeLengthInBytes, encodedTextLengthInBytes));
        }