package cs211.examples;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Scanner;
/**
* This is a sample class to show you how to do some simple bit level reading
* and writing from and to files.
*
* The basic strategy for both reading and writing is to work with a byte
* array and using bit-wide operators to access the individual bits in the array.
*
* @author C. Andrews
*
*/
public class BinaryDataExample {
private byte[] buffer; // an array of bytes that we will use as our buffer
private int currentBit; // the address of our current location in the buffer
/**
* This function adds a single bit to the buffer.
*
* The function takes in a single number, which should be a 1 or 0 and
* adds it to the end of the buffer (the location of currentBit). This
* currently does no error checking to make sure the number is actually a
* 1 or a 0.
*
* @param b the "bit"
*/
private void addBit(int b){
// figure out which byte in the array we want
int currentByte = currentBit / 8;
// use mod and shifting to set the precise bit in that byte
buffer[currentByte] |= b << (7 - currentBit % 8);
// increment currentBit to point to the next open space in the buffer
currentBit ++;
}
/**
* This is a simple example that uses the above function to write data out
* to a file.
*
* In this example, I set the buffer to a very small 10 bytes. You will
* probably want something larger. That said, no matter how large you make
* it, you will probably need more room. There are two ways to handle this.
* You could write an array expansion method and copy to a longer array, or
* you could write the buffer to the file, empty it, and start over.
*
* @throws IOException
*/
private void writeExample() throws IOException {
File f = new File("writeExample");
FileOutputStream stream = new FileOutputStream(f);
// create the buffer and initialize the pointer to the end of the buffer
buffer = new byte[10];
currentBit = 0;
// write a bunch of bits into the buffer
addBit(1);
addBit(0);
addBit(0);
addBit(1);
addBit(1);
addBit(1);
addBit(1);
addBit(1);
addBit(0);
addBit(0);
addBit(0);
addBit(1);
addBit(1);
addBit(1);
// write the buffer into the file
stream.write(buffer, 0, currentBit/8 + 1);
// close the file
stream.close();
}
/**
* Return the next bit available in the buffer.
*
* This is just the inverse of the addBit function. We find the right byte.
* Shift the byte to put the bit we are interesting in the rightmost position,
* and then AND it with 1 to remove all of the other bits.
*
* @return the next bit
*/
private int nextBit(){
int bit = buffer[currentBit/8] >> (7 - currentBit % 8) & 1;
currentBit++;
return bit;
}
/**
* Example of reading bits from a file.
*
* The general approach we will take is to read the entire file into the buffer.
* We can then use the inverse of the addBit() function to read each bit out
* individually.
* @throws IOException
*/
private void readExample() throws IOException {
// we will just open the file we wrote above and read it back
File f = new File("writeExample");
FileInputStream stream = new FileInputStream(f);
// ask how many bytes are in the file
int numBytes = stream.available();
// create a buffer big enough to hold the file
buffer = new byte[numBytes];
currentBit = 0;
// read in the file
stream.read(buffer);
// close the stream
stream.close();
// print out all of the bits in the file
for (int i = 0; i < buffer.length * 8; i ++){
System.out.println(nextBit());
}
}
/**
* This runs the two examples in sequence, write and then read (so read has
* something to work with.
*
* @param args
* @throws IOException
*/
public static void main(String[] args) throws IOException {
BinaryDataExample bde = new BinaryDataExample();
bde.writeExample();
bde.readExample();
}
}