CS1501 -- Fall 2003 // Intro to using binary files in Java for input and output. This program will // simply copy any file, whether it is text, executable or anything else. // It will then output the 8 leftmost bits and the 8 rightmost bits of an // integer to demonstrate some binary operations. import java.io.*; import javax.swing.*; //FOR RECITATION: //Maybe we could print out copies of this original code and distribute them to // the students. (Of course they should have line numbers down the side.) // Recommend highly that they compile and run this program to see what it does. // Emphasize that it demonstrates two separate things, as detailed above. These // two tasks it demonstrates are unrelated. //At first, I think we should just emphasize that all files are "binary files" // and clarify that a "binary file" is not a text file that you open up in notepad // that is full of 1's and 0's. If you have a text file of 1's and 0's, and you // read the file byte by byte, the byte you will be reading are the ascii values that // represent those 1's and 0's, I think the ascii values are like 30 and 31 or something, // so each 1 is 8-bits that represent the number 31 in binary, and each 0 is 8 bits that // represent the number 30 in binary. //We may also consider starting off with a quick tutorial on binary numbers // just as a refresher b/c I noticed some blank faces when I started recitation // with the 1's and 0's representing base ten numbers this morning. public class binaryio { public static void main(String [] args) { //I believe if the students use these two object types for //reading from and writing to binary files, they'll be able to //complete the assignment.... FileInputStream infile = null; FileOutputStream outfile = null; //Although DataInputStream and DataOutputStream //are also object types they can use that may be more flexible //and powerful as they have methods that can read //16-bits (readUnsignedShort) and write a byte or a short, etc String ifname = null; // string for name of input file String ofname = null; // string for name of output file int ch; while (true) { try { //get filename from user ifname = JOptionPane.showInputDialog(null, "File name?"); //give it to the input file stream infile = new FileInputStream(ifname); break; } catch (IOException e) { System.out.println("File " + ifname + " could not be opened"); } } ofname = ifname + ".cop"; try { outfile = new FileOutputStream(ofname); //They can read the input file that they will be compressing (or //decompressing) just like this... ch = infile.read(); // Read ahead because we must test for end of file while (ch != -1) { outfile.write(ch); // <-- This is how they will write the // compressed data (or the freshly decoded data) // to a binary file ch = infile.read(); // get the next byte } infile.close(); outfile.close(); } catch (IOException e1) { System.out.println("Some bogusness with the file"); System.exit(0); } //The tricky thing for them will be processing the byte once they've read it in // and converting it to the encoded bits, then gathering encoded bits one byte // at a time before writing each byte. One student I heard was planning to pull // out each bit and store the bits into integer arrays, then manipulate them as // integers, then write out every 8 bits. //For example, if you need to write the following sequence of bits: // 00001010 (the value here is 10) // you could do the following: // int value = 10; // outfile.write(value); // since the write command writes the 8 least significant bits of any integer, // which is a 32-bit data type. They can look up all the specs for the // FileOutputStream methods at the java 1.5.0 API at java.sun.com. //If they use this method, they could calculate the base ten value of the bit // sequence, store it in an integer, then use the write command to add it to // the output file. //This next section shows how to extract a certain number of bits from an // integer value. They might need this after they have read in a byte, then // stored it into an integer, and now they want to extract the bits from it. FileOutputStream newFile = null; try { //This output file will hold the extracted bits newFile = new FileOutputStream("wacky.out"); //This is is the value we will be extracting bits from //(It's binary representation is: 2^30 + 2^24 + 2^7 + 2^3 + 2^1) int val = 1090519178; //This is the number of bits we are extracting from the left //and the right side of the integer variable: int bits = 8; //the bits extracted from the left will be stored int leftout = 0; //the bits extracted from the right will be stored: int rightout = 0; //right-shift out 24 bits of the integer value, //leaving the top 8 bits only, now in the bottom eight slots leftout = val >> (32-bits); // should be 01000001 = 65 //left-shift out 24 bits of the integer value, //leaving the bottom 8 bits only, now in the top eight slots, //then right-shift these bottom 8 bits back to the bottom // eight slots rightout = (val << (32 - bits)) >> (32 - bits); // should be 10001010 = 138 //write these two values to the output file. newFile.write(leftout); newFile.write(rightout); newFile.close(); //if you open this file now in notepad, you will see the letter // "A," which corresponds to the ascii code 65, and a strange // symbol, which corresponds to the ascii code 138. //read the values back in from the file we just wrote to. FileInputStream reFile = new FileInputStream("wacky.out"); int lval = reFile.read(); int rval = reFile.read(); reFile.close(); //print out the values 65 and 138 System.out.println("leftmost " + bits + " bits = " + lval); System.out.println("rightmost " + bits + " bits = " + rval); } catch (Exception e) { System.out.println("Some exception " + e + " has occurred"); } } }