Beispiel #1
0
        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)
            {
                writer.Close();
                return(new CompressionInfo(0, 0, 0, 0));
            }
            HuffmanTree      tree      = HuffmanTree.GenerateHuffmanTree(text);
            HuffmanCodeTable codeTable = new HuffmanCodeTable(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++;
            }
            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++;
            }
            try
            {
                writer.Write((byte)((FileFormatVersion << 2) | (treeLengthInBytes >> 16)));
                writer.Write((byte)(treeLengthInBytes >> 8));
                writer.Write((byte)(treeLengthInBytes));
                writer.Write((byte)((bitsOfLastByteOfTree << 4) | bitsOfLastByteOfEncodedText));
                WriteBuffer(writer, treeBuffer, treeBitPosition);
                WriteBuffer(writer, encodedTextBuffer, encodedTextBitPosition);
            }
            catch
            {
                throw;
            }
            finally
            {
                writer.Close();
            }

            return(new CompressionInfo(text.Length, 4, treeLengthInBytes, encodedTextLengthInBytes));
        }
 public ListNode(HuffmanTree tree)
 {
     Tree = tree;
 }
Beispiel #3
0
        public static string Decode(string filename)
        {
            byte[] buffer;

            try
            {
                buffer = File.ReadAllBytes(filename);
            }
            catch
            {
                throw;
            }

            if (buffer.Length == 0)
            {
                return("");
            }

            int fileFormatVersion = buffer[0] & 0xFC;

            if (fileFormatVersion > FileFormatVersion)
            {
                throw new FormatException("File '" + filename + "' has a newer format (file format version " + fileFormatVersion.ToString("00") + "), or is invalid or corrupted.");
            }

            if (buffer.Length < 8)
            {
                throw new FormatException("File '" + filename + "' is invalid or corrupted.");
            }

            int treeLengthInBytes    = ((int)(buffer[0] & 0x03) << 16) | ((int)buffer[1] << 8) | ((int)buffer[2]);
            int bitsOfLastByteOfTree = buffer[3] >> 4;
            int bitsOfLastByteOfText = buffer[3] & 0x0F;

            if (bitsOfLastByteOfTree < 1 || bitsOfLastByteOfTree > 8 || bitsOfLastByteOfText < 1 || bitsOfLastByteOfText > 8 || treeLengthInBytes < 3 || treeLengthInBytes > 147456 || buffer.Length < 5 + treeLengthInBytes)
            {
                throw new FormatException("File '" + filename + "' is invalid or corrupted.");
            }

            HuffmanTree tree            = new HuffmanTree();
            int         treeBitPosition = 32;

            try
            {
                DecodeTree(tree, buffer, ref treeBitPosition, (3 + treeLengthInBytes) * 8 + bitsOfLastByteOfTree);
            }
            catch (FormatException)
            {
                throw new FormatException("File '" + filename + "' is invalid or corrupted.");
            }


            string decodedText = "";

            if (tree.IsLeaf())
            {
                for (int i = 4 + treeLengthInBytes; i < buffer.Length; i++)
                {
                    if (buffer[i] != 0)
                    {
                        throw new FormatException("File '" + filename + "' is invalid or corrupted.");
                    }
                }
                int numOfChars = (buffer.Length - treeLengthInBytes - 5) * 8 + bitsOfLastByteOfText;

                for (int i = 0; i < numOfChars; i++)
                {
                    decodedText += tree.Character;
                }

                return(decodedText);
            }

            HuffmanTree currentNode = tree;

            for (int i = 4 + treeLengthInBytes; i < buffer.Length - 1; i++)
            {
                for (byte mask = 0x80; mask != 0; mask >>= 1)
                {
                    if ((buffer[i] & mask) != 0)
                    {
                        currentNode = currentNode.Right;
                    }
                    else
                    {
                        currentNode = currentNode.Left;
                    }

                    if (currentNode == null)
                    {
                        throw new FormatException("File '" + filename + "' is invalid or corrupted.");
                    }

                    if (currentNode.IsLeaf())
                    {
                        decodedText += currentNode.Character;
                        currentNode  = tree;
                    }
                }
            }

            for (byte mask = 0x80, count = 0; count < bitsOfLastByteOfText; mask >>= 1, count++)
            {
                if ((buffer[buffer.Length - 1] & mask) != 0)
                {
                    currentNode = currentNode.Right;
                }
                else
                {
                    currentNode = currentNode.Left;
                }

                if (currentNode == null)
                {
                    throw new FormatException("File '" + filename + "' is invalid or corrupted.");
                }

                if (currentNode.IsLeaf())
                {
                    decodedText += currentNode.Character;
                    currentNode  = tree;
                }
            }

            return(decodedText);
        }