/// <summary> /// Main method for Huffman III /// </summary> /// <param name="args">Program arguments</param> /// <param name="stdOut">Standard output stream</param> /// <param name="fileOut">Optimal Output Binary stream</param> /// <param name="fileIn">Optimal Input Binary stream</param> public static void Run_FileDecodeWithTree(string[] args, TextWriter stdOut, BinaryWriter fileOut = null, BinaryReader fileIn = null) { if (args.Length != 1) { stdOut.WriteLine("Argument Error"); return; } string fileName = args[0]; if (fileName.Length <= 5 || !fileName.Substring(fileName.Length - 5).Equals(".huff")) { stdOut.WriteLine("Argument Error"); return; } try { if (fileIn == null) { fileIn = new BinaryReader(File.OpenRead(fileName)); } if (fileOut == null) { fileOut = new BinaryWriter(File.Open(fileName.Substring(0, fileName.Length - 5), FileMode.Create)); } HuffmansTree tree = new HuffmansTree(stdOut, fileIn); DecodeFileBytes(tree, fileIn, fileOut); } catch (IOException) { stdOut.WriteLine("File Error"); } finally { if (fileIn != null) { fileIn.Close(); } if (fileOut != null) { fileOut.Close(); } if (stdOut != null) { stdOut.Close(); } } }
/// <summary> /// Main method for Huffman II /// </summary> /// <param name="args">Program arguments</param> /// <param name="stdOut">Standard output stream</param> /// <param name="fileOut">Optimal Output Binary stream</param> /// <param name="fileIn">Optimal Input Binary stream</param> public static void Run_FileEncodeWithTree(string[] args, TextWriter stdOut, BinaryWriter fileOut = null, BinaryReader fileIn = null) { if (args.Length != 1) { stdOut.WriteLine("Argument Error"); return; } string fileName = args[0]; try { if (fileIn == null) { fileIn = new BinaryReader(File.OpenRead(fileName)); } if (fileOut == null) { fileOut = new BinaryWriter(File.Open(fileName + ".huff", FileMode.Create)); } var byteFrequency = ReadFileByteCounts(fileIn); HuffmansTree tree = new HuffmansTree(stdOut, byteFrequency); var encodedNodes = tree.GetEncodedNodes(); PrintHeaderBinary(fileOut); tree.PrintPrefixBinary(fileOut); fileIn.BaseStream.Position = 0; EncodeFileBytes(encodedNodes, fileIn, fileOut); } catch (IOException) { stdOut.WriteLine("File Error"); } finally { if (fileIn != null) { fileIn.Close(); } if (fileOut != null) { fileOut.Close(); } if (stdOut != null) { stdOut.Close(); } } }
/// <summary> /// Main method for Huffman I /// </summary> /// <param name="args">Program arguments</param> /// <param name="stdOut">Standard output stream</param> /// <param name="fileIn">Input Binary file stream</param> public static void Run_FileReadTreeBuild(string[] args, TextWriter stdOut, BinaryReader fileIn = null) { if (args.Length != 1) { stdOut.WriteLine("Argument Error"); return; } string fileName = args[0]; try { if (fileIn == null) { fileIn = new BinaryReader(File.OpenRead(args[0])); } Dictionary <byte, ulong> byteFrequency = ReadFileByteCounts(fileIn); HuffmansTree tree = new HuffmansTree(stdOut, byteFrequency); tree.PrintPrefixReadable(); } catch (IOException) { stdOut.WriteLine("File Error"); } }
/// <summary> /// Decodes encoded stream of input stream. /// </summary> /// <param name="tree">Initialized Huffman tree, loaded from encoded file.</param> /// <param name="fileIn">Encoded input stream.</param> /// <param name="fileOut">Output stream.</param> internal static void DecodeFileBytes(HuffmansTree tree, BinaryReader fileIn, BinaryWriter fileOut) { fileIn.BaseStream.Position = 0; if (!Program.CheckHeader(fileIn)) { throw new IOException(); //Structural error, path in tree not found } while (fileIn.ReadUInt64() != 0) { ; } if (tree == null) { fileOut.Write(""); return; } int maxBufferSize = 100000; //Maximum for Huffman I => 1000000 HuffmansTree.Node actual = tree.root; var outBuffer = new List <byte>(); while (fileIn.BaseStream.Position != fileIn.BaseStream.Length) { long diff = fileIn.BaseStream.Length - fileIn.BaseStream.Position; bool lastBatch = diff < maxBufferSize ? true : false; int maxSize = lastBatch ? (int)(diff) : maxBufferSize; byte[] bytesBuffer = fileIn.ReadBytes(maxSize); BitArray bits = new BitArray(bytesBuffer); for (int i = 0; i < bits.Length; i++) { if (actual.Order == 0) { if (actual.Sum == 0) { if (lastBatch && i > bits.Length - 8) { break; } else { throw new IOException(); // Sum shouldn't be zero yet } } outBuffer.Add(actual.Code); actual.Sum--; actual = tree.root; } if (bits[i] == false) { if (actual.Left == null) { throw new IOException(); //Structural error, path in tree not found } actual = actual.Left; } else { if (actual.Right == null) { throw new IOException(); //Structural error, path in tree not found } actual = actual.Right; } } if (actual.Order == 0 && actual.Sum > 0) { outBuffer.Add(actual.Code); actual.Sum--; actual = tree.root; } fileOut.Write(outBuffer.ToArray()); outBuffer = new List <byte>(); } }