10 if (node ==
nullptr)
return;
63 infile.open(infilePath, std::ios::in | std::ios::binary);
65 throw std::runtime_error(
"Input Error : \'" + infilePath.string() +
"\' couldn't be opened");
86 outfile.write(
reinterpret_cast<char*
>(&fileCount),
sizeof(fileCount));
89 std::string file_path;
91 unsigned int fileSize = fs::file_size(file);
92 outfile.write(
reinterpret_cast<char*
>(&fileSize),
sizeof(fileSize));
94 if (fs::is_directory(inputName))
95 file_path = fs::relative(file, inputName).string();
97 file_path = file.filename().string();
99 outfile.write(file_path.c_str(), file_path.size());
105 infile.open(infileName, std::ios::in | std::ios::binary);
107 throw std::runtime_error(
"[compressFiles] one or more files in the directory cant be opened");
112 chr = (chr << 1) ^ (binCode -
'0');
114 if (bufferSize == 0) {
115 outfile.write(
reinterpret_cast<char*
>(&chr),
sizeof(chr));
125 fs::path outfilePath = fs::canonical(inputName).replace_extension(
".huf");
126 if (fs::path(inputName) == outfilePath) {
127 outfilePath.replace_filename(outfilePath.stem().string() +
"_1.huf");
129 std::ofstream outfile(outfilePath, std::ios::out | std::ios::binary | std::ios::trunc);
131 throw std::runtime_error(
"Output Error : compressed file couldn't be created");
138 writeBody(chr, bufferSize, file.string(), outfile);
142 chr = chr << bufferSize;
143 outfile.write(
reinterpret_cast<char*
>(&chr),
sizeof(chr));
153 std::cout <<
"Huffman Compression\n";
154 std::cout << std::string(19,
char(205)) << std::endl;
155 std::cout <<
inputFiles.size() <<
" file(s) detected\n";
160 int fileNameWidth = file.filename().string().length() + 3;
161 if (fileNameWidth > fieldWidth)
162 fieldWidth = fileNameWidth;
163 totalSize += fs::file_size(file);
167 std::cout <<
"Filename : "<<std::setw(fieldWidth) << std::left << file.filename() <<
" | size: " << fs::file_size(file) <<
" bytes"<< std::endl;
170 std::cout <<
"\nCompressing ..." << std::endl;
171 auto start = std::chrono::steady_clock::now();
173 std::cout <<
"Reading frequency ..." << std::endl;
178 std::cout <<
"Creating Huffman Tree ..." << std::endl;
181 std::cout <<
"Generating CodeMap ..." << std::endl;
184 std::cout <<
"Encoding to File ..." << std::endl;
187 std::cout <<
"Cleaning Up ..." << std::endl;
190 std::cout <<
"Success: Compression Completed.\n" << std::endl;
191 std::cout <<
"Compressed File Name\n" << outfilePath.filename() << std::endl;
192 std::cout <<
"Compressed File Location\n" <<
"\"" << outfilePath.parent_path().string() <<
"\"\n" << std::endl;
194 auto stop = std::chrono::steady_clock::now();
195 auto duration = std::chrono::duration_cast<std::chrono::duration<double>>(stop - start);
197 int outputSize = fs::file_size(outfilePath);
198 std::cout << std::setw(22) <<
"Total Input Size" <<
" = "<< totalSize <<
" bytes" << std::endl;
199 std::cout << std::setw(22) <<
"Compressed File Size" <<
" = " << outputSize <<
" bytes" << std::endl;
200 std::cout << std::setw(22) <<
"Compression Ratio" <<
" = " << std::setprecision(4) << float(totalSize - outputSize) / totalSize * 100 <<
" % " << std::endl;
201 std::cout << std::setw(22) <<
"Compression Time" <<
" = " << duration.count() <<
" seconds\n" << std::endl;
205 if (!fs::is_regular_file(infileName))
206 throw std::runtime_error(
"ERROR : Please enter a valid file path");
214 if (!fs::is_directory(directoryName))
215 throw std::runtime_error(
"ERROR : Please enter a valid directory path");
217 for (
auto&& entry : fs::recursive_directory_iterator(directoryName)) {
218 if (entry.is_regular_file()) {
227 for (
auto&& infileName : infileNames) {
228 if (fs::is_regular_file(infileName))
231 throw std::runtime_error(
"ERROR : Please enter a valid file path");
constexpr auto INTERNAL_NODE_CHARACTER
Constants for Huffman Tree.
constexpr auto FILE_NAME_SEPARATOR
Constants for file Header.
This class models a node structure used for building Huffman Binary Tree.
BinNode * getRightChild() const
void setRightChild(BinNode *)
sets parameter node as left child of the caller node instance.
void setLeftChild(BinNode *)
sets parameter node as left child of the caller node instance.
BinNode * getLeftChild() const
char getCharacter() const
void deleteTree(BinNode *node)
Frees all heap storage associated with the Huffman Tree.
fs::path writeIntoFile(const std::string &infileName)
Write the header and body section to compressed file.
void compressFolder(const std::string &directoryName)
Compresses a directory and its entire content recursively.
BinNode * rootNode
Root node for Huffman tree.
void clear()
Resets all the attributes for next compression operation.
void readFrequency()
Reads entire input file and finds frequency of each unique characters.
HashMap< char, std::string > codeMap
Prefix-free binary code for each value of the source symbol.
void compressFile(const std::string &infileName)
Compresses a single input file.
HashMap< char, int > frequency
Frequency of occurrence for each unique symbol in the source.
void compress(const std::string &infileName)
Utility function to compress file.
BinNode * createHuffmanTree()
Creates a Huffman Tree form unique characters along with their frequency of occurrences.
void compressFiles(std::initializer_list< std::string > infileNames)
Compresses multiple source files into single compressed(.huf) file.
void scanFile(const fs::path &infilePath)
Validates input file path and proceeds on reading frequency.
void writeBody(char &chr, int &bufferSize, const std::string &infileName, std::ofstream &writer)
Write the body section to compressed file.
std::ifstream infile
Instance of ifstream class for reading characters from source.
std::vector< fs::path > inputFiles
List of input files given by the user.
void writeHeader(const std::string &inputName, std::ofstream &writer)
Write the header section to compressed file.
void writeTree(std::ofstream &writer, BinNode *head)
Write the entire Huffman tree in to the file header section using a pre-order traversal algorithm.
void generateHuffmanCode(BinNode *rootNode, std::string codeString)
Generates prefix code for each unique characters in the source.
ValueType get(const KeyType &key) const
void clear()
Removes all entries from this map.
This class models Priority Queue in which values are processed in order of priority.
T dequeue()
Removes and returns the highest priority value.
void enqueue(const T &)
Adds value to the priority queue