I have created my own Bit-Level IO stream. It works perfectly, however there is noticable speed issues for large streams.
Can anyone suggest how i may optimize these classes further?
/*
$Log: BitInputStream.java,v $
Revision 1.2 2005/02/04 13:51:05 moogie
-fixed FileDataInfo transfer
-fixed Directory Transfer
-made hashtables synchronized
-fixed miscelanous bugs
-modified the client gui to use the multiple ID file data request.
Revision 1.1 2005/02/01 06:36:35 moogie
- added FileName String Compression (Huffman)
- no longer storing the full path on serverside... is now being derived
- added binary RunLengthEncoding for potential use in file transfer
*/
/**
* @author Nicholas Klaebe
*/
package compression;
import java.io.*;
public class BitInputStream
{
InputStream fis; // The parent IO stream
int count; // The current bit position in the current byte
long totalCount; // The number of bits written
byte value; // The current byte;
byte[] buffer; // The byte buffer containing bytes read in from the parent IO stream
int buffCount; // the current position in the buffer
int buffSize; // the size of the populated buffer
boolean returnVal;
private static final int EOF_INT=-1;
/**
* Constructor
* @param fis1 The base inputStream
* @param size size of the input buffer
*/
public BitInputStream(InputStream fis1,int size)
{
count=0;
buffer=new byte[size];
buffCount=0;
totalCount=0;
fis=fis1;
}
/**
* read in a single bit
* @return bit read
* @throws IOException
*/
public boolean read() throws IOException
{
if (count==0)
{
if (buffCount==0)
{
buffSize=0;
while (buffSize==0)
{
buffSize=fis.read(buffer,0,buffer.length);
}
if (buffSize==EOF_INT)
{
throw new IOException("END OF FILE");
}
}
value=buffer[buffCount];
buffCount++;
if (buffCount==buffSize) buffCount=0;
}
returnVal=(((value>>(7-count) &0x01)>0)?true:false);
count++;
totalCount++;
if (count==8) count=0;
return returnVal;
}
/**
* reads in the next char, if not on a 8bit boundary then the stream is aligned to the next byte
* @return byte read
* @throws IOException
*/
public char readChar() throws IOException
{
byte[] b= new byte[1];
alignToNextByte();
fis.read(b);
totalCount+=8;
return (char) b[0];
}
/**
* aligns the bit stream to the next byte boundary
* @throws IOException
*/
public void alignToNextByte() throws IOException
{
while (count!=0)
{
read();
}
}
/**
* read in a specified number of bits
* @param bits the number of bits to be read (between 1 and 64)
* @return a long integer containg the bits read
* @throws IOException
*/
public long read(int bits) throws IOException
{
long val=0;
int mask=0x01;
boolean[] bitsRead=new boolean[bits];
for (int i=0;i<bits;i++)
{
bitsRead[i]=read();
}
for (int j=bits-1;j>-1;j--)
{
val=val<<1;
if (bitsRead[j])
{
val=val|mask;
}
}
return val;
}
/**
* attempts to read bytes into the array given
* @param temp the array being populated
* @param start the starting index
* @param end the ending index
* @return the bytes read in
* @throws IOException
*/
public int read(byte[] temp,int start,int end) throws IOException
{
totalCount+=end-start;
return fis.read(temp,start,end);
}
}
/*$Log: BitOutputStream.java,v $
/*Revision 1.1 2005/02/01 06:36:35 moogie
/*- added FileName String Compression (Huffman)
/*- no longer storing the full path on serverside... is now being derived
/*- added binary RunLengthEncoding for potential use in file transfer
/**/
/**
* @author Nicholas Klaebe
*/
package compression;
import java.io.*;
public class BitOutputStream
{
int value; // The byte in which the encoded bits are firstly stored.
int count; // The number of bits written into value.
byte[] buffer; // A byte buffer which is filled with 'value' each time value is full. Used for wirting to file.
int buffCount; // The current number of 'values' written into the buffer.
long masterCount; // The overall count of bits that have been written
OutputStream fos;
/**
* constructor
* @param fos1 The outputstream which this bit stream writes to
*/
public BitOutputStream(OutputStream fos1)
{
fos=fos1;
value=0;
count=0;
buffer=new byte[4096];
buffCount=0;
masterCount=0;
}
/**
* Writes the passed value (temp) to the file using the given number of bits
* @param temp the value to be written
* @param bits the number if bits to write
* @throws IOException
*/
public void write(long temp,int bits) throws IOException
{
for (int j = 0, mask = 1; j < bits; j++, mask <<= 1)
{
value=value<<1;count++;
if ((temp & mask) > 0)
{
value=value|0x01;
}
addToBuffer();
}
}
/**
* write a single bit to the stream
* @param bit The bit to write
* @throws IOException
*/
public void write(boolean bit) throws IOException
{
value=value<<1;count++;
if (bit)
{
value=value|0x01;
}
addToBuffer();
}
/**
* writes a single char (converted to a byte) to the output stream aligning with the next byte boundary
* @param c the char to write
* @throws IOException
*/
public void write(char c) throws IOException
{
flush();
byte[] b=new byte[1];
b[0]=(byte) c;
fos.write(b);
masterCount+=8;
}
/**
* adds bits stored in 'value' to a buffer which will be saved to a file
* if the current bit count since last storing into the buffer is less than 8 then return without adding it to the buffer
* @throws IOException
*/
public void addToBuffer() throws IOException
{
masterCount++;
if (count<8) return;
//byte temp=(byte) (value);
buffer[buffCount]=(byte) (value);;
buffCount++;
if (buffCount==buffer.length)
{
fos.write(buffer,0,buffCount);
buffCount=0;
}
value=0;
count=0;
}
/**
* writes a single byte to the output stream aligning with the next byte boundary
* @param b the byte to write
* @throws IOException
*/
public void write(byte[] b) throws IOException
{
flush();
fos.write(b);
}
/**
* align the output stream with the next byte boundary
* @throws IOException
*/
public void flush() throws IOException
{
// pad out the last byte if necessary
if (count>0)
{
masterCount+=(8-count-1);
value=value<<(8-count);
count=8;
addToBuffer();
}
if (buffCount>0)
{
fos.write(buffer,0,buffCount);
buffCount=0;
}
}
/**
* close the output stream
* @throws IOException
*/
public void close() throws IOException
{
flush();
fos.close();
}
}