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; }
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); }