init
This commit is contained in:
209
p3/HuffmanCompressor.java
Normal file
209
p3/HuffmanCompressor.java
Normal file
@@ -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");
|
||||
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user