diff options
| author | pants <niklasjo2004@gmail.com> | 2026-09-21 14:16:34 -0700 |
|---|---|---|
| committer | pants <niklasjo2004@gmail.com> | 2026-09-21 14:16:34 -0700 |
| commit | 81ba9eb66f8284d8760012973f84cdbe617ceb94 (patch) | |
| tree | 466432644e9e3fd66ee183ec53a1f10abb1b7faa /p3/HuffmanCompressor.java | |
Diffstat (limited to 'p3/HuffmanCompressor.java')
| -rw-r--r-- | p3/HuffmanCompressor.java | 209 |
1 files changed, 209 insertions, 0 deletions
diff --git a/p3/HuffmanCompressor.java b/p3/HuffmanCompressor.java new file mode 100644 index 0000000..55228f1 --- /dev/null +++ b/p3/HuffmanCompressor.java @@ -0,0 +1,209 @@ +import java.io.*; +import java.util.*; + +public class HuffmanCompressor { + private String filename; + + public static final int CHAR_MAX = 255; // max char value + public static final int MAKE_CODE = 1; + public static final int COMPRESS = 2; + public static final int DECOMPRESS = 3; + public static final int ROUND_TRIP = 4; + + public HuffmanCompressor(String filename) { + if (!filename.endsWith(".txt")) { + throw new IllegalArgumentException( + "This compressor only works on text files!"); + } + this.filename = filename.split(".txt")[0]; + } + + public void makeCode() throws IOException { + System.out.println("I am about to make the Huffman code for " + + filename + ".txt..."); + FileInputStream input = new FileInputStream(filename + ".txt"); + int[] count = new int[CHAR_MAX]; + int n = input.read(); + while (n != -1) { + int prev = n; + count[n]++; + n = input.read(); + + // Remove added newline by ed + if (n == -1 && prev == 10) { + count[prev]--; + } + } + + // Build the code; open the output file; save the code + System.out.println("\tI built up a frequency table of the " + + "characters in your file."); + System.out.println("\tNow, I'm going to call your HuffmanCode(int[]) " + + "constructor using that frequency table."); + HuffmanCode t = new HuffmanCode(count); + + System.out.println("\tOkay! Now, I am going to save the code (using " + + "your save method) to the file " + filename + + ".code!"); + PrintStream output = new PrintStream(new File(filename + ".code")); + t.save(output); + System.out.println("...I am done making the Huffman Code!"); + } + + public void compress(boolean debug) throws IOException { + System.out.println("I am about to attempt to COMPRESS " + + filename + ".txt:"); + /* We must make the code before we can compress... */ + this.makeCode(); + System.out.println("\tNow that I have the Huffman Code, I am going " + + "to use the huffman code file created by"); + System.out.println("\tyour save() method to compress the contents " + + "into " + filename + ".short!"); + + String[] codes = new String[CHAR_MAX]; + Scanner codeInput = new Scanner(new File(filename + ".code")); + while (codeInput.hasNextLine()) { + int n = Integer.parseInt(codeInput.nextLine()); + codes[n] = codeInput.nextLine(); + } + + // Open file to be compressed; open output file + FileInputStream input = new FileInputStream(this.filename + ".txt"); + BitOutputStream output = new BitOutputStream( + new PrintStream(this.filename + ".short"), debug); + + // Print out the debug binary to a .debug file + FileOutputStream debugOut = null; + if (debug) { + debugOut = new FileOutputStream(this.filename + ".debug"); + } + + // Do the compression + int n = input.read(); + while (n != -1) { + if (codes[n] == null) { + // check if this is actually an error, or an ed added newline + if (!(n == 10 && input.read() == -1)) { + System.out.println("Your code file has no code for " + n + + " (the character '" + (char) n + "')"); + System.out.println("exiting..."); + System.exit(1); + } + n = -1; + } else { + for (int i = 0; i < codes[n].length(); i++) { + output.write(codes[n].charAt(i) - '0'); + // Write to the .debug file + if (debugOut != null) { + debugOut.write(codes[n].charAt(i)); + } + } + n = input.read(); + } + } + input.close(); + output.close(); + System.out.println("...I am done compressing the file"); + } + + public void decompress(boolean printToConsole) throws IOException { + System.out.println("I am about to attempt to DECOMPRESS " + + filename + ".short:"); + + System.out.println("\tTo do this, I must first read in the huffman " + + "code used to compress the file."); + System.out.println("\tI will use your HuffmanCode(Scanner) " + + "constructor!"); + // Open code file and construct tree + Scanner codeInput = new Scanner(new File(this.filename + ".code")); + HuffmanCode t = new HuffmanCode(codeInput); + + // Open compressed file; open output + BitInputStream input = new BitInputStream(this.filename + ".short"); + PrintStream output = System.out; + if (!printToConsole) { + System.out.println("\tNow, I will decompress the file using your " + + "translate() method and save"); + System.out.println("\tthe output into " + this.filename + ".new"); + output = new PrintStream(new File(this.filename + ".new")); + } + else { + System.out.println("\tNow, I will decompress the file using your " + + "translate() method and display it on the console"); + } + + // Decompress the file + t.translate(input, output); + output.close(); + System.out.println("...I am done decompressing the file"); + } + + public static void main(String[] args) throws IOException { + Scanner console = new Scanner(System.in); + + System.out.println("Welcome to the CSE 123 Huffman Compressor!"); + System.out.println(); + + String filename; + + do { + System.out.print("Which file would you like to work with (it " + + "must be a txt file)? "); + filename = console.nextLine().trim(); + } while (!filename.endsWith(".txt")); + + System.out.println(); + + int choice = -1; + + while (choice == -1) { + System.out.println("Would you like to:"); + System.out.println("\t(1) make a huffman code,"); + System.out.println("\t(2) compress a file,"); + System.out.println("\t(3) decompress a file, or"); + System.out.println( + "\t(4) do a compression followed by a decompression"); + System.out.print("1-4? "); + String choiceStr = console.nextLine().trim(); + try { + choice = Integer.parseInt(choiceStr); + if (choice < 1 || choice > 4) { + choice = -1; + } + } catch(NumberFormatException e) { + /* Don't change choice; so, the loop will repeat. */ + } + } + + boolean debug = false; + if (choice == COMPRESS || choice == ROUND_TRIP) { + debug = prompt( + console, + "Would you like to debug the compressed file (y/n)? "); + } + + boolean toConsole = false; + if (choice == DECOMPRESS || choice == ROUND_TRIP) { + toConsole = !prompt( + console, + "Would you like to print the result to a file (y/n)? "); + } + + HuffmanCompressor huffman = new HuffmanCompressor(filename); + switch (choice) { + case 1: huffman.makeCode(); break; + case 2: huffman.compress(debug); break; + case 3: huffman.decompress(toConsole); break; + case 4: + huffman.compress(debug); + huffman.decompress(toConsole); + break; + } + } + + public static boolean prompt(Scanner console, String message) { + System.out.print(message); + return console.nextLine().trim().toLowerCase().startsWith("y"); + + } +} |
