created 06/23/00; revised 08/31/08, 11/20/2012

Programming Exercises


Exercise 1 – Magic Number

Examine the first few bytes of several GIF images with a hex dump and verify that the first six bytes of the file are the ASCII characters 'GIF89a'. Now look at some image files of other formats. What are the first several bytes of JPEG images? of TIFF images? of MP3 audio files?

Click here to go back to the main menu.


Exercise 2 – Binary vs Text

Write a program that creates a text file and outputs the integers one to one million to it. Include statements in the program that time how long it takes to run. (Use System.currentTimeMillis() and the start and end of the program). Write a version of the program that does buffering (using BufferedWriter()) and a version that does not. What is the difference in times?

Now write a program that creates a binary file and outputs the ints one to one million. Use a DataOutputStream with writeInt(). Include statements in the program that time how long it takes to run. Write a version of the program that does buffering (using BufferedOutputStream()) and a version that does not. What is the difference in times? What is the difference compared to text output? Fill in a table like the following:

Writing not buffered buffered
Text File    
Binary File    

Next, write a program that reads in the text file one one million text integers and computes their sum Use the nextInt() method of Scanner. Use the constructor of Scanner that takes a File parameter. (See chapter 23.) Write a program that does the same with the binary file. Determine how long each program takes. Fill in a table like the following:

Reading not buffered buffered
Text File NA  
Binary File    

It is difficult to read in text integers without using Scanner. Scanner does buffering, so its times fall into the "buffered" cell of the table. Skip unbuffered input of text integers (unless you want: this will take some study of Java documentation).

Click here to go back to the main menu.


Exercise 3 – Finally

Rewrite the ReadIntEOF program to use a finally block to ensure that a file that has been opened is told to close. Of course, the close() might fail.

Click here to go back to the main menu.


Exercise 4 – Testing the File Copy Program

Copy the file copy program to Notepad, compile it, and run it. Use the program to copy its own source file to a temporary file. Look at the copy to see if it is OK. Rename the copy to the name of the original file (thus deleting the original). Compile the copy to see if there are problems.

Now use the program to copy its own bytecode file (the *.class file) to a temporary file. Rename the copy to the name of the original bytecode file. Run the new bytecode file. It should work. (On Unix systems you may have to use the chmod command to make the copy executable.)

Click here to go back to the main menu.


Exercise 5 – Data Compressor

Write a program that reads in a binary file of 4-byte int data. All the data is expected to be in the range -32768 to 32767, which will fit into a 2-byte short. The program writes a binary file that contains the same integers as the input file (in the same order), but each integer is now a short. Write an error message whenever an input value is outside the expected range, and write a 0 to output.

For data in the expected format, this program will compress the file to 50 percent of its original size. Of course, any file not in this format will be turned into complete garbage. It might be interesting to try.

The Data Translator program from the previous chapter can be used to create data to test this program.

Click here to go back to the main menu.


Exercise 6 – Input File with Header

Say that you have several files of integer data using various formats: byte, short, and int. Each file starts out with a header like this:

First four bytes:    an int that says how many bytes there are per
                     integer in this file: 1, 2, or 4.

The data in the designated format immediately follow the header.

Write a program that uses a file like that as input. The program checks the header to determine how to read in the rest of the data. Then it reads in each integer and writes it (in character form) on the monitor screen.

Modify the Data Translator program from the previous chapter so that it creates files suitable for testing this program. It is OK to make several versions of the Data Translator program, one for each type of testing file.

Click here to go back to the main menu.


Exercise 7 – Encryption and Decryption Program

Modify the file copy program so that the copy is encrypted (encoded). Each byte of the source file is altered by reversing each bit. For example,

input byteoutput byte
0011010111001010
0000000011111111
1000000001111111

This operation is sometimes called a bit-wise complement. "Bit-wise" means that each bit is treated independently of all the others. "Complement" is just another word for reversal.

All the bits in an integer can be reversed as follows:

int value;

value = ~value;

The "~" (tilde) is the bit-wise complement operator. Visually it looks like a reversal of up and down. It reverses all the bits in value, even though you may be interested in only the low-order byte. But since the operation is bit-wise, the result for the low-order byte is the same no matter how many others are affected.

Encrypt a text file using your program. For amusement purposes, look at the result with Notepad. Now use the program again to encrypt the encrypted file. Look at the result with Notepad. Will you need to write a program to decrypt (decode) files?

This is not a very secure method of encrypting a file. Java has other bit-wise operators that can be used to scramble bit patterns in other ways.

Click here to go back to the main menu.


Exercise 8 – Hex Dump

Write a program that reads in any file byte-by-byte and writes each byte to the monitor using two characters per byte. The eight bits of each byte are divided into two 4-bit groups, for example:

01011101 ==> 0101 1101

Each 4-bit group is represented with one character according to the following table:

Name 01 2 3 4 5 6 7
Pattern0000 0001 0010 0011 0100 0101 0110 0111
 
Name 89 A B C D E F
Pattern1000 1001 1010 1011 1100 1101 1110 1111

Even though you are only interested in bytes, it is convenient to do all your bit manipulation using int variables. To make all bits in the int zero except for the low-order 4 bits, do this:

int data, lowFour;

lowFour = data & 0X0000000F ;

The "&" is the bit-wise AND operator. Now lowFour will contain one of the 16 possible patterns in its low-order 4 bits. To make all bits in the int zero except for the other 4 bits of the low-order byte, do this:

int data, highFour;

highFour = data & 0X000000F0 ;

To shift those four bits right so that they occupy the low-order 4 bit positions, do this:

highFour = highFour>>>4 ;

Display each byte of the input file using two characters followed by a space. Display 16 bytes per line (fewer on the last line). Here is an example of the program working:

C:\Programs>DIR
06/23/00  10:52p                 1,859 HexDump.class
06/23/00  10:52p                 2,855 HexDump.java
06/23/00  08:23p                    60 ints.dat

C:\Programs>java HexDump ints.dat
00 00 00 0C 00 00 03 FF FF FF FF C8 00 01 4B 2D
00 00 00 00 FF FF DB 65 00 00 00 22 00 00 02 8E
FF FF FF E9 FF FF FE DA 00 00 00 12 FF FF FF E7
00 00 00 AD 00 00 00 2D FF FF FF FE
C:\Programs>

Click here to go back to the main menu.


End of Exercises.