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