// // enchuf.cpp // // (c) Copyright 2000 William A. McKee. All rights reserved. // // Created April 29, 2000 // // Compress a file using Huffman encoding. // // Compiled with VC++ 6.0: cl /Ox /GX enchuf.cpp // #include #include #include #include #include #include "huffman.h" using namespace std; static int obc = 0; static char och = 0; static int input_count = 0; static int output_count = 0; void output (ofstream & outf, string & str) { for (int i = 0; i < str.size (); i++) { int bit = str [i] - '0'; och |= bit << (7-obc); if (++obc == 8) { outf << och; output_count ++; obc = 0; och = 0; } } } void flush_output (ofstream & outf) { if (obc != 0) { outf << och; output_count ++; obc = 0; och = 0; } } int main (int argc, char * * argv) { int i; if (argc < 3) { cerr << "usage: enchuf " << endl; return EXIT_FAILURE; } int * hist = new int [256]; for (i = 0; i < 256; i++) hist [i] = 0; ifstream inf (argv [1], ios::in | ios::binary); if (inf.fail ()) { cerr << "error : unable to open input file '" << argv [1] << "'." << endl; return EXIT_FAILURE; } ofstream outf (argv [2], ios::out | ios::binary); if (outf.fail ()) { cerr << "error : unable to open output file '" << argv [2] << "'." << endl; return EXIT_FAILURE; } clock_t start_time = clock (); for (;;) { char ch; inf.read (&ch, 1); if (inf.eof ()) break; hist [static_cast(ch)] ++; } vector data; data.push_back (new Leaf (0, -1)); // end of file marker for (i = 0; i < 256; i++) { if (hist [i] != 0) { data.push_back (new Leaf (hist [i], i)); } } delete [] hist; Table table; Node * const root = BuildHuffman (data); if (root != NULL) { root -> Encode (string (), table); delete root; } int cnt = 0; for (i = table.Base (); i <= table.Summit (); i++) if (!table [i].huffman_string.empty ()) if (i != -1) cnt ++; if (cnt > 0) { char ch = cnt - 1; outf << ch; output_count ++; } for (i = table.Base (); i <= table.Summit (); i++) if (!table [i].huffman_string.empty ()) { if (i != -1) { char ch = i; outf << ch; output_count ++; } char ch = table [i].huffman_string.size (); outf << ch; output_count ++; } for (i = table.Base (); i <= table.Summit (); i++) if (!table [i].huffman_string.empty ()) output (outf, table [i].huffman_string); inf.clear (); inf.seekg (0); for (;;) { char ch; inf.read (&ch, 1); if (inf.eof ()) break; input_count ++; output (outf, table [static_cast(ch)].huffman_string); } output (outf, table [-1].huffman_string); flush_output (outf); clock_t end_time = clock (); double timer = (double) (end_time - start_time) / CLOCKS_PER_SEC; cout << input_count << " characters input." << endl; cout << output_count << " characters output." << endl; cout << (input_count == 0 ? 0 : (input_count - output_count) * 100 / input_count) << "% reduction in size." << endl; cout << timer << " seconds." << endl; cout << (timer == 0.0 ? 0.0 : input_count / timer) << " characters per second." << endl; return EXIT_SUCCESS; }