Note: Writing the compressed data one bit at
a time can be tricky. You might want to pre-process the stream into
bytes before writing to disk.
Your Uncompress program should go through the following steps:
-
open the input file for reading,
-
load in the header information,
-
build a data structure which maps codewords to symbols (e.g. '01' -> X,
'1101' -> Q),
-
open the output file for writing,
-
scan the body of the compressed file, translating codewords into symbols,
and writing each symbol to the output file.
Note: Huffman coding is prefix-free, meaning
that no codeword is a prefix of another codeword. This means that you
can read the bits one at a time until it matches a known codeword.
Again, reading one bit at a time can be tricky, so it might be helpful to
translate the file's byte stream into a stream of bits (Booleans) before
completing step 5.
Guidelines
-
You must work in teams of 2 people.
-
Include a file named README, which contains the names of your team
members, and any additional information/documentation about your program.
-
You may use anything from the Java Collections framework (some you will
probably need: PriorityQueue, HashMap, Vector, Stack). It is
probably easiest to make your own (sub)class for the coding tree.
-
Your code must be thoroughly documented with javadoc.
-
Your code must adhere to the data format specified above.
Specifically, it must handle all provided example data.
-
Use good OO design and engineering practice. Use exceptions where
appropriate. Design your methods and data structures BEFORE you
start coding.
-
You should have at least three source files:
-
Compress.java: main program for the compressor
-
Uncompress.java: main program for the uncompressor
-
Huffman.java: contains all the Huffman coding data structures and
methods.
Data Format
Your compressed files must adhere to the following format:
-
4 bytes (integer): the number of bytes in the
original file. This tells you how many codewords to look
for.
-
4 bytes (integer): the size of the
alphabet.
-
for each symbol in the alphabet:
-
1 byte: the symbol itself
-
1 byte: the number of bits in its
codeword
-
1-? bytes: the codeword, padded to the right
with 0-bits (see example below).
-
1-? bytes: the compressed data, padded to the
right with 0-bits.
Example:
If the input file consists of:
ABB
Then the compressed file, represented in hexadecimal, looks like:
00 00 00
03
Length of the
file
00 00 00 02
Size of the
alphabet
41 01 00
Coding
information for the first symbol (A)
42 01 80
Coding
information for the second symbol (B)
60
The data
stream
Note that even though both symbols have a one-bit codeword (A -> 0, B
-> 1), they are padded up to the nearest byte in the compressed file.
(note that 8 = 1000 in binary, so a 1 padded with 0's) These extra 0-bits
should not be interpreted as data.
There are three example compressed files available
under /home/linux/ieng6/cs100f/public/p1data/.
For one of them, the original file is also provided. You can use this
to test whether your uncompress program is operating correctly by running
the following commands:
java Uncompress
test.txt.p1z test.txt.new
diff -q test.txt
test.txt.new
If there is no output from the diff command, then your uncompressed
file is correct. (See man
diff for more information on this utility.)
Another utility that may be useful
is hexdump, which
displays the contents of a file in hexadecimal. This will come in
handy when testing your compress program. For example, the command:
hexdump -C
test.txt.p1z
outputs:
00000000 00
00 01 2b 00 00 00 18 44 04 10 45 04 30 46 04
|...+....D..E.0F.|
00000010 40
47 04 50 41 05 a8 42 05 f8 43 04 00 4c 04 c0
|@G.PA..B..C..L..|
00000020 4d 04 e0 0a 04 d0 48 04 60 49 04 80
4a 04 90 4b |M.....H.`I..J..K|
...
The first column is the (32-bit) address of the first byte in the
line, and each remaining column is a byte in the file, displayed in
hex. The contents of the file are displayed in ASCII in the far right
column.
Turning in
When your program is finished, create a tar file including your source code
and class files by running:
tar czvf
LASTNAME.tar.gz *.java *.class README
Then, submit your tar file by running:
turnin -c cs100f -p
p1 LASTNAME.tar.gz