public OrderedLinkedList <TreeNode <CharacterFrequency> > TransferListToTree(OrderedLinkedList <TreeNode <CharacterFrequency> > orderedNodeList) { while (orderedNodeList.Count != 1) { TreeNode <CharacterFrequency> least = orderedNodeList.GetFirst(); orderedNodeList.RemoveFirst(); TreeNode <CharacterFrequency> nextLeast = orderedNodeList.GetFirst(); orderedNodeList.RemoveFirst(); TreeNode <CharacterFrequency> combinedLeast = new TreeNode <CharacterFrequency>(new CharacterFrequency('\0', (least.Element.Frequency + nextLeast.Element.Frequency))); combinedLeast.Left = least; combinedLeast.Right = nextLeast; orderedNodeList.Add(combinedLeast); } return(orderedNodeList); }
//Method used for compressing files static void Compress(string input, string output) { //start of method //Initilize variables int totalChars = 0; //Counts number of characters in file, used for decompression purposes BinaryTree <CharacterFrequency> charTree = new BinaryTree <CharacterFrequency>(); StreamReader read = new StreamReader(input); //Create a dictionary of CharacterFrequency objects with the int key being the ascii code of each character IDictionary <int, CharacterFrequency> charDictionary = new Dictionary <int, CharacterFrequency>(); //Read entire file character by character... while (!read.EndOfStream) { int i = read.Read(); //checks if Dictionary contains the char i... if (!charDictionary.ContainsKey(i)) { //if not add new record to dictionary charDictionary.Add(i, new CharacterFrequency((char)i, 1)); } else { //if so increment the frequency of this record charDictionary[i].increment(); } totalChars++; } read.Close(); //Create ordered linked list of TreeNode<CharacterFrequency> objects OrderedLinkedList <TreeNode <CharacterFrequency> > orderedNodeList = new OrderedLinkedList <TreeNode <CharacterFrequency> >(); //Go throughs each KeyValuePair in the CharacterFrequency dicitionary.. foreach (KeyValuePair <int, CharacterFrequency> c in charDictionary) { //Make a new TreeNode of the CharacterFrequency value from c... TreeNode <CharacterFrequency> node = new TreeNode <CharacterFrequency>(c.Value); //add into the ordered linked list of TreeNode<CharacterFrequency> orderedNodeList.Add(node); } //Run a method in the binary tree to convert the ordered node list into a single node with branching children container all other nodes //and return and set said node as the root node of the tree charTree.Insert(charTree.TransferListToTree(orderedNodeList).GetFirst(), Relative.Root); //Run a method from the tree to return a list of BinaryPath objects LinkedList <BinaryPath <CharacterFrequency> > binaryTable = charTree.BinaryTable(charTree.Root); //Removes all nodes from the binarytable that have a null character as they cannot show up in a file var binary = binaryTable.First; while (binary != null) { var nextNode = binary.Next; if (binary.Value.Element.Character == '\0') { binaryTable.Remove(binary); } binary = nextNode; } //Byte writing section int bitPosition = 7; //creates an int that determines what bit in the byte to set byte y = 0; //creates the byte to set and write with BinaryWriter binaryWriter = null; bool error = true; while (error) { try { binaryWriter = new BinaryWriter(File.Create(CheckFile(output))); error = false; } catch (UnauthorizedAccessException ex) { MessageBox.Show("You do not have the permissions needed to write to this folder"); } } StreamReader streamReader = new StreamReader(input); //string of the entire table, to used to append to the beginning of the output file. Will be read by out in decompression process string tableText = String.Empty; //Take the total characters from the input file and append to the beginning of the output file tableText += totalChars + "~~~"; //Take table and write to output file foreach (BinaryPath <CharacterFrequency> bp in binaryTable) { tableText += bp.Element.Character + bp.Path + ";"; } binaryWriter.Write(tableText); //Compression process while (!streamReader.EndOfStream) { //Read each character from file.. int i = streamReader.Read(); //Find path of character from binary table... string path = binaryTable.FirstOrDefault(obj => obj.Element.Character == (char)i).Path; //Iterate through each character in path... foreach (char c in path) { //If bitposition = 0 we have set all other bits if (bitPosition == 0) { //if character is '1' set bit at bitposition in byte to 1 using bitwise OR(|) if (c == '1') { y = (byte)(y | (byte)Math.Pow(2, bitPosition)); } //Writes byte to output file binaryWriter.Write(y); //Resets byte and bitposition y = 0; bitPosition = 7; } //If bitposition != 0 else { //if character is '1' set bit at bitposition in byte to 1 using bitwise OR(|) if (c == '1') { y = (byte)(y | (byte)Math.Pow(2, bitPosition)); } //progresses bitposition down 1 to next bit in byte bitPosition--; } } } //Close stream reader read.Close(); //write final byte to output file and close BinaryWriter binaryWriter.Write(y); binaryWriter.Close(); //Output to command prompt to let user know file is finished being compressied, end program Console.WriteLine($"File has been compressed to the file {output}"); }