0

I'm currently working with a Huffman Tree to compress/decompress text files. Currently my problem is that when writing bytes and reading them, I lose any leading 0's in my numbers.

In my OutputStream class, my writeBit()method, I am fed one bit at a time and when my count of bits reaches 8, I write the byte to the file. Currently using a String to build this binary number, although the problem occurs when actually writing the bit.

HuffmanOutputStream.java:

/**
* Created by Sully on 3/20/2017.
*/

import java.io.IOException;


public class HuffmanOutputStream extends BitOutputStream {

private int count = 0;
private String bytes = "";

public HuffmanOutputStream(String filename, String tree, int totalChars) {
    super(filename);
    try {
        d.writeUTF(tree);
        d.writeInt(totalChars);
    } catch (IOException e) {
    }
}

public void writeBit(int bit) {
    //PRE   bit ==  0   ||  bit ==  1
    if (count < 8) {
        bytes += bit;
        count++;
    }
    try {

        if (count == 8) {
            d.writeByte(Integer.parseInt(bytes, 2));
            count = 0;
            bytes = "";
        }

    } catch (IOException e) {
        e.printStackTrace();
    } 
}


public void close() {

}
}

An example of when things go wrong, for my text file, the first byte that I construct is 01100001, although when I use Integer.parseInt(byte,2), the integer given is 97, which when it is then read as a binary number, only returns 1100001. As Huffman Trees rely on these 0's being included, how can I keep this 0 in place? Also to make sure that it is read correctly with the 0's remaining in place?

HuffmanInputStream.java:

/**
* Created by Sully on 3/20/2017.
*/

import java.io.IOException;

public class HuffmanInputStream extends BitInputStream {
  private String tree;
  private int totalChars;

  private int currentByte;
  private int bitCount;
  private static final int BYTE_SIZE = 8;
  private int[] bufferedBits = new int[BYTE_SIZE];


public HuffmanInputStream(String filename) {
    super(filename);

    try {
        tree = d.readUTF();
        totalChars = d.readInt();
        currentByte = 0;
        bitCount = 8;

    } catch (IOException e) {
    }
}


public int readBit() {

    if (currentByte == -1) {
        return -1;
    }


    if (bitCount == 8) {
        try {
            currentByte = d.read();
            if(currentByte == -1){
                return -1;
            }
            String binary = Integer.toBinaryString(currentByte);
            for (int x = 0; x < binary.length(); x++) {
                bufferedBits[x] = Character.valueOf(binary.charAt(x));
            }
            bitCount = 0;
        } catch (IOException e) {
            e.printStackTrace();
        }

    }

    int val = bufferedBits[bitCount];

    bitCount++;

    return val % 2;


}

public String getTree() {
    return tree;
}

public int totalChars() {
    return totalChars;
}

public void close() {
    try {
        d.close();
    } catch (IOException e) {
        e.printStackTrace();
    }
}
}

I know it's a bit lengthy of a question but any help is greatly appreciated!

Sully Brooks
  • 395
  • 2
  • 7
  • 19
  • It sounds like your problem is just with `Integer.toBinaryString`. – Louis Wasserman Apr 20 '17 at 17:16
  • @LouisWasserman do you mind explaining what the problem might be? I'm just trying to understand why I'm losing these 0's. Do I need to do some sort of padding/bit shifting? – Sully Brooks Apr 20 '17 at 17:19
  • 1
    This has _nothing_ to do with the numbers or padding or bit shifting, and everything to do with your choice of `Integer.toBinaryString` as your means of converting from an `int` to a sequence of 0s and 1s. `Integer.toBinaryString` is not going to generate any leading zeroes at all. – Louis Wasserman Apr 20 '17 at 17:20
  • @LouisWasserman do you have any suggestions as to how I could maintain these 0's when reading the bytes? – Sully Brooks Apr 20 '17 at 17:27

1 Answers1

2

I assume that you're looking to have enough leading 0s to make the length of the String that is returned from Integer#toBinaryString 8; the following code will achieve this for you:

String binary = String.format("%8s", Integer.toBinaryString(currentByte)).replace(' ', '0');
Jacob G.
  • 26,421
  • 5
  • 47
  • 96