为霍夫曼编码写入位

时间:2015-05-30 19:35:34

标签: java compression huffman-code

我对编程很新,我试图使用这种方法进行压缩,我已经有了正确的0和1序列,我需要一点一点地编写它,所以我使用了一个名为BitOutputStream和BitInputStream的类写它(我没有做),问题是我从写入的文件中读取的内容与我的序列不同,这是我以前编写的代码:

public void writeCompressed() throws IOException{ 
    BitOutputStream fop2 = new BitOutputStream(
                    new ObjectOutputStream(
                            new FileOutputStream(
                                    "C:\\Users\\David\\Documents\\davidCompress.dabc")));
    for (int i = 0; i < secuenciaFinal.length(); i++) {
        if (secuenciaFinal.charAt(i) == '1') {
            fop2.write1Bit();//lee la cadena y si contiene 1 escribe in 1 bit en mi archivo1
        } else if (secuenciaFinal.charAt(i) == '0') {
            fop2.write0Bit();//si la cadena contiene 0 bits escribe 0 bits
        } else {
            //fop2.missingBits();
        }
    } 
    fop2.close();        
}

其中“secuenciaFinal”是我要保存的序列,但是当我读到它时,我得到一个完全不同的序列:

public void writeDecompressed(String path) throws IOException{ 
    InputStream is = new FileInputStream(path);
    BitInputStream bis = new BitInputStream(is);
    String textBits = "", OriginalText ="";

    while(bis.available()>0)
        textBits += bis.readBit() +"";
    TreeNode node = root;
    for (int i = 0; i < textBits.length(); i++) {
        if(!node.isLeaf()){
            if(Integer.parseInt(textBits.charAt(i)+"") == 0)
            {node = node.getleftSon();}
            else if(Integer.parseInt(textBits.charAt(i)+"") == 1)
            {node = node.getrightSon();}
            else
                System.out.println("No se encontró 1 ni 0");
        }else{
            OriginalText += node.getData();  
            node = root;
        }  
    }
    bis.close();        
}

我已经被困在这几个小时了,不知道该怎么办,我做错了什么?或者是BitOutputStream和BitInputStream类的故障? 提前致谢。 那些类很大,所以我不得不删除它的所有注释,以适应这里的BitInputStream乱码:

public class BitInputStream extends InputStream {

private static final int DEFAULT_BUFFER_SIZE = 4096;

private byte[] buf;

private int bufSize;

private int pos;

private int bits;

private int bitSize;

private int unreadSize;

private InputStream in;

private boolean fillByteBuffer() throws IOException {
    if (in == null) {
        throw new IOException("The stream is closed!");
    }

    if ((bufSize = in.read(buf, 0, buf.length)) == -1) {
        pos = -1;
        unreadSize = 0;
        return false;
    }
    pos = 0;
    return true;
}

public BitInputStream(InputStream in, int size) {
    if (in == null) {
        throw new NullPointerException("The stream in is null");
    }

    if (size <= 0) {
        throw new IllegalArgumentException("A buffer size of " + size
                + " is illegal!");
    }

    buf = new byte[size];
    this.in = in;
}

public BitInputStream(InputStream in) {
    this(in, DEFAULT_BUFFER_SIZE);
}


public BitInputStream(String fileName, int size) throws FileNotFoundException {
    this(new FileInputStream(fileName), size);
}


public BitInputStream(String fileName) throws FileNotFoundException {
    this(new FileInputStream(fileName));
}


public static BitInputStream fromFile(String fileName)
        throws FileNotFoundException {
    return new BitInputStream(new FileInputStream(fileName));
}


public static BitInputStream fromByteArray(byte[] b) {
    if (b == null) {
        throw new NullPointerException("The byte array b is null!");
    }
    int size = DEFAULT_BUFFER_SIZE;
    if (b.length < size) {
        size = b.length;
    }
    return new BitInputStream(new ByteArrayInputStream(b), size);
}


@Override
public int available() throws IOException {
    if (in == null) {
        throw new IOException("The stream is closed!");
    }

    return bitSize + 8 * (bufSize - pos + in.available());
}

@Override
public int read() throws IOException {
    unreadSize = 8; // the maximal number of bits to be unread

    if (bitSize < 8) // the bit buffer needs more bits
    {
        if (pos >= bufSize) // does the byte array need a refill?
        {
            if (fillByteBuffer() == false) {
                return -1;
            }
        }

        bits <<= 8; // makes room for 8 new bits
        bits |= (buf[pos++] & 0xff); // a byte (8 bits) is added

        return (bits >> bitSize) & 0xff; // 8 bits are returned

    } // end of if (bitSize < 8)

    bitSize -= 8;
    return (bits >> bitSize) & 0xff; // 8 bits are returned
}


public int readBit() throws IOException {
    unreadSize = 1;

    if (bitSize <= 0) // the bit buffer is empty
    {
        if (pos >= bufSize) // does the byte array need a refill?
        {
            if (fillByteBuffer() == false) {
                return -1;
            }
        }
        bits = (buf[pos++] & 0xff); // 8 bits are added
        bitSize = 8; // bitSize is updated

    } // if (bitSize <= 0)

    bitSize--;
    return (bits >> bitSize) & 1;
}


public int readBits(int numberOfBits) throws IOException {
    if (numberOfBits < 0) {
        throw new IllegalArgumentException("Cannot read " + numberOfBits
                + " bits!");
    }


    // / 1. numberOfBits <= 25, the most common case /////////

    if (numberOfBits <= 25) {
        while (bitSize < numberOfBits) // will not create overflow
        {
            if (pos >= bufSize) // does the byte array need a refill?
            {
                if (fillByteBuffer() == false) {
                    return -1;
                }
            }

            bits <<= 8; // makes room for 8 new bits
            bits |= (buf[pos++] & 0xff); // a byte (8 bits) is added
            bitSize += 8; // bitSize is updated

        } // end while

        bitSize -= numberOfBits; // bitSize is updated
        unreadSize = numberOfBits; // unreadSize is updated

        return (bits >> bitSize) & ~(-1 << numberOfBits);
    }

    // / 2. numberOfBits > 25 /////////////////////

    while (bitSize < 25) // will not create overflow
    {
        if (pos >= bufSize) // does the byte array need a refill?
        {
            if (fillByteBuffer() == false) {
                return -1;
            }
        }

        bits <<= 8; // makes room for 8 new bits
        bits |= (buf[pos++] & 0xff); // a byte (8 bits) is added
        bitSize += 8; // bitSize is updated
    } // end while

    // / 3. numberOfBits < bitSize /////////////////////

    if (numberOfBits < bitSize) // enough bits in the buffer!
    {
        bitSize -= numberOfBits; // bitSize is updated
        unreadSize = numberOfBits; // unreadSize is updated

        return (bits >> bitSize) & ~(-1 << numberOfBits);
    }

    // / 4. numberOfBits == bitSize /////////////////////

    if (numberOfBits == bitSize) {
        // To continue we need to be sure that numberOfBits is not
        // out of range, i.e. not equal to 32 or greater.

        if (numberOfBits > 31) {
            throw new IllegalArgumentException("Cannot read " + numberOfBits
                    + " bits!");
        }

        bitSize = 0; // bitSize is updated
        unreadSize = numberOfBits; // unreadSize is updated

        return bits & ~(-1 << numberOfBits);
    }

    // / 5. numberOfBits > bitSize /////////////////////



    int copy = bits & ~(-1 << bitSize); // a bit buffer copy

    if (pos >= bufSize) // does the byte array need a refill?
    {
        if (fillByteBuffer() == false) {
            return -1;
        }
    }
    bits <<= 8; // makes room for 8 new bits
    bits |= (buf[pos++] & 0xff); // a byte (8 bits) is added
    int diff = numberOfBits - bitSize;
    bitSize = 8 - diff; // bitSize is updated
    unreadSize = diff + 24; // unreadSize is updated     
    return (copy << diff) | ((bits >> bitSize) & ~(-1 << diff));
}

public int skip() throws IOException {
    unreadSize = 0; // no unread subsequent to a skip

    if (bitSize < 8) // more bits to the bit buffer
    {
        if (pos >= bufSize) // does the byte array need a refill?
        {
            if (fillByteBuffer() == false) {
                int skipSize = bitSize;
                bitSize = 0;
                return skipSize; // equal to the number of bits skipped
            }
        }

        bits <<= 8; // make room for 8 bits
        bits |= (buf[pos++] & 0xff); // a byte (8 bits) is added

        return 8; // 8 bits are skipped

    } // end of if (bitSize < 8)

    bitSize -= 8;
    return 8; // 8 bits are skipped
}


@Override
public long skip(long n) throws IOException {
    throw new UnsupportedOperationException();
}

public void unreadBit() throws IOException {
    if (in == null) {
        throw new IOException("The stream is closed!");
    }

    if (unreadSize <= 0) {
        throw new IllegalStateException("No bits to unread!");
    }

    unreadSize--;
    bitSize++;
}


public void unreadBits() throws IOException {
    if (in == null) {
        throw new IOException("The stream is closed!");
    }

    bitSize += unreadSize;
    unreadSize = 0;
}


public void unreadBits(int numberOfBits) throws IOException {
    if (in == null) {
        throw new IOException("The stream is closed!");
    }

    if (numberOfBits < 0 || numberOfBits > unreadSize) {
        throw new IllegalArgumentException("Illegal number of bits!");
    }

    unreadSize -= numberOfBits;
    bitSize += numberOfBits;
}


public int unreadSize() throws IOException {
    if (in == null) {
        throw new IOException("The stream is closed!");
    }

    return unreadSize;
}


public void insertBit(int bit) throws IOException {
    if (in == null) {
        throw new IOException("The stream is closed!");
    }

    if (bitSize == 32) {
        throw new IllegalStateException("No bits can be inserted!");
    }

    bits = ((bits & (-1 << bitSize)) << 1) | ((bit & 1) << bitSize)
            | (bits & ((1 << bitSize) - 1));

    if (unreadSize > 0) {
        unreadSize--;
    }
    bitSize++;
}


public void insert0Bit() throws IOException {
    if (in == null) {
        throw new IOException("The stream is closed!");
    }

    if (bitSize == 32) {
        throw new IllegalStateException("No bits can be inserted!");
    }

    bits = ((bits & (-1 << bitSize)) << 1) | (bits & ((1 << bitSize) - 1));

    if (unreadSize > 0) {
        unreadSize--;
    }
    bitSize++;
}

public void insert1Bit() throws IOException {
    if (in == null) {
        throw new IOException("The stream is closed!");
    }

    if (bitSize == 32) {
        throw new IllegalStateException("No bits can be inserted!");
    }

    bits = ((bits & (-1 << bitSize)) << 1) | (1 << bitSize)
            | (bits & ((1 << bitSize) - 1));

    if (unreadSize > 0) {
        unreadSize--;
    }
    bitSize++;
}

public void insertBits(int value, int numberOfBits) throws IOException {
    if (in == null) {
        throw new IOException("The stream is closed!");
    }

    if (numberOfBits < 0 || numberOfBits > insertSize()) {
        throw new IllegalArgumentException("numberOfBits too large!");
    }

    if (numberOfBits == 32) // bitSize = 0
    {
        bits = value;
    } else {
        bits = (bits & ((1 << bitSize) - 1))
                | ((bits & (~((1 << bitSize) - 1))) << numberOfBits)
                | ((value & ((1 << numberOfBits) - 1)) << bitSize);
    }
    unreadSize -= numberOfBits;

    if (unreadSize < 0) {
        unreadSize = 0;
    }
    bitSize += numberOfBits;
}

public int insertSize() throws IOException {
    if (in == null) {
        throw new IOException("The stream is closed!");
    }

    return 32 - bitSize;
}  
@Override
protected void finalize() throws Throwable {
    super.finalize();
    if (in != null) {
        close();
    }
} 
@Override
public void close() throws IOException {
    // a second call to close will have no effect
    if (in == null) {
        return;
    }
    in.close();
    in = null;
    buf = null;
    pos = -1;
    bufSize = -1;
    bitSize = -1;
}
} 

这里是BitOutputStream:

public class BitOutputStream extends OutputStream {

private static final int DEFAULT_BUFFER_SIZE = 4096;

private byte buf[];

private int bufSize;

private int pos;

private int bits;

private int bitSize;

private OutputStream out;

public BitOutputStream(OutputStream out, int size) {
    if (out == null) {
        throw new NullPointerException("The stream out is null");
    }

    if (size <= 0) {
        throw new IllegalArgumentException("The size(" + size + ") <= 0");
    }

    buf = new byte[bufSize = size];
    this.out = out;
}

public BitOutputStream(OutputStream out) {
    this(out, DEFAULT_BUFFER_SIZE);
}

public BitOutputStream(String fileName, int size)
        throws FileNotFoundException {
    this(new FileOutputStream(fileName), size);
}


public BitOutputStream(String fileName) throws FileNotFoundException {
    this(new FileOutputStream(fileName), DEFAULT_BUFFER_SIZE);
}

public static BitOutputStream toFile(String fileName)
        throws FileNotFoundException {
    return new BitOutputStream(new FileOutputStream(fileName));
}

public static BitOutputStream toFile(String fileName, boolean append)
        throws FileNotFoundException {
    return new BitOutputStream(new FileOutputStream(fileName, append));
}
private void flushBuffer() throws IOException {
    if (out == null) {
        throw new IOException("The stream is closed!");
    }

    if (pos > 0) {
        out.write(buf, 0, pos);
        pos = 0;
    }
} // end flushBuffer


public void writeBit(int bit) throws IOException {
    bits <<= 1;         // a bit can now be added
    bits |= (bit & 1);  // the last bit of the parameter bit is added
    bitSize++;          // bitSize is updated

    if (bitSize >= 8) // a byte can be moved to the byte buffer
    {
        bitSize = 0;

        // the byte buffer is flushed if it is full
        if (pos >= bufSize) {
            flushBuffer();
        }

        buf[pos++] = (byte) bits;  // a byte is moved
    }
} // end writeBit

public void write0Bit() throws IOException {
    bits <<= 1;        // adds a 0-bit
    bitSize++;         // bitSize is updated

    if (bitSize >= 8) // a byte can be moved to the byte buffer
    {
        bitSize = 0;

        // the byte buffer is flushed if it is full
        if (pos >= bufSize) {
            flushBuffer();
        }

        buf[pos++] = (byte) bits;  // a byte is moved
    }
} // end write0Bit

public void write1Bit() throws IOException {
    bits <<= 1;   // a bit can now be added
    bits |= 1;    // adds a 1-bit
    bitSize++;    // bitSize is updated

    if (bitSize >= 8) // a byte can be moved to the byte buffer
    {
        bitSize = 0;

        // the byte buffer is flushed if it is full
        if (pos >= bufSize) {
            flushBuffer();
        }

        buf[pos++] = (byte) bits;  // a byte is moved
    }
} // end write1Bit


@Override
public void write(int b) throws IOException {
    bits <<= 8;          // 8 bits can now be added
    bits |= (b & 0xff);  // adds the 8 rightmost bits of b

    // the byte buffer is flushed if it is full
    if (pos >= bufSize) {
        flushBuffer();
    }

    buf[pos++] = (byte) (bits >> bitSize);  // a byte is moved

} // end write

public void writeBits(int value, int numberOfBits) throws IOException {
    if (numberOfBits < 0) {
        throw new IllegalArgumentException("Cannot write " + numberOfBits
                + " bits!");
    }

    if (numberOfBits <= 25) // the most common case
    {
        bits <<= numberOfBits;  // will not create overflow

        bits |= (value & ((1 << numberOfBits) - 1));  // the bits are added
        bitSize += numberOfBits;  // the bitsize is updated

        while (bitSize >= 8) {
            bitSize -= 8;

            // the byte buffer is flushed if it is full
            if (pos >= bufSize) {
                flushBuffer();
            }

            buf[pos++] = (byte) (bits >> bitSize);  // a byte is moved
        }
    } else if (numberOfBits <= 32) {
        int k = numberOfBits - 25;          // 1 <= k <= 7
        bits <<= 25;                        // 25 bits can now be added
        bits |= (value >> k) & 0x1ffffff;   // 25 bits are added
        bitSize += 25;                      // bitSize is updated

        // the bit buffer contains at least 25 bits,
        // 24 of them are moved to the byte buffer

        bitSize -= 8;
        if (pos >= bufSize) {
            flushBuffer();
        }
        buf[pos++] = (byte) (bits >> bitSize);

        bitSize -= 8;
        if (pos >= bufSize) {
            flushBuffer();
        }
        buf[pos++] = (byte) (bits >> bitSize);

        bitSize -= 8;
        if (pos >= bufSize) {
            flushBuffer();
        }
        buf[pos++] = (byte) (bits >> bitSize);

        bits <<= k;                         // k bits can now be added
        bits |= (value & ((1 << k) - 1));   // the rightmost k bits of value
        bitSize += k;                       // bitSize is updated

        if (bitSize >= 8) // 2 <= bitSize <= 15
        {
            bitSize -= 8;
            if (pos >= bufSize) {
                flushBuffer();
            }
            buf[pos++] = (byte) (bits >> bitSize);  // a byte is moved
        }
    } else {
        throw new IllegalArgumentException("Cannot write " + numberOfBits
                + " bits!");
    }

} // end writeBits


public void writeBits(int value) throws IOException {
    // must find the number of significant bits of value

    int signifcantBits = 31, v = value;

    if (v >>> 16 == 0) {
        signifcantBits -= 16;
        v <<= 16;
    }
    if (v >>> 24 == 0) {
        signifcantBits -= 8;
        v <<= 8;
    }
    if (v >>> 28 == 0) {
        signifcantBits -= 4;
        v <<= 4;
    }
    if (v >>> 30 == 0) {
        signifcantBits -= 2;
        v <<= 2;
    }

    signifcantBits += v >>> 31;

    bitSize += signifcantBits;

    if (bitSize <= 32) {
        bits <<= signifcantBits;  // will not create overflow
        bits |= value;            // the signifcantBits are added

        while (bitSize >= 8) {
            bitSize -= 8;
            if (pos >= bufSize) {
                flushBuffer();
            }
            buf[pos++] = (byte) (bits >> bitSize);
        }
    } else {
        int k = bitSize - 32;
        bits <<= signifcantBits - k;
        bits |= value >>> k;

        if (pos >= bufSize) {
            flushBuffer();
        }
        buf[pos++] = (byte) (bits >> 24);

        if (pos >= bufSize) {
            flushBuffer();
        }
        buf[pos++] = (byte) (bits >> 16);

        if (pos >= bufSize) {
            flushBuffer();
        }
        buf[pos++] = (byte) (bits >> 8);

        if (pos >= bufSize) {
            flushBuffer();
        }
        buf[pos++] = (byte) bits;

        bits = value;
        bitSize = k;
    }

} // end writeBits


public void writeLeftBits(int value, int numberOfBits) throws IOException {
    if (numberOfBits < 0) {
        throw new IllegalArgumentException("Cannot write  a negative ("
                + numberOfBits + ") number of bits!");
    }

    if (numberOfBits <= 25) // the most common case
    {
        bits <<= numberOfBits;  // will not create overflow

        bits |= (value >>> (32 - numberOfBits));  // the bits are added
        bitSize += numberOfBits;  // the bitsize is updated

        while (bitSize >= 8) {
            bitSize -= 8;

            // the byte buffer is flushed if it is full
            if (pos >= bufSize) {
                flushBuffer();
            }

            buf[pos++] = (byte) (bits >> bitSize);  // a byte is moved
        }
    } else if (numberOfBits <= 32) {
        bits <<= 25;                        // 25 bits can now be added
        bits |= (value >>> 7);              // 25 bits are added
        bitSize += 25;                      // bitSize is updated

        // the bit buffer contains at least 25 bits,
        // 24 of them are moved to the byte buffer

        bitSize -= 8;
        if (pos >= bufSize) {
            flushBuffer();
        }
        buf[pos++] = (byte) (bits >> bitSize);

        bitSize -= 8;
        if (pos >= bufSize) {
            flushBuffer();
        }
        buf[pos++] = (byte) (bits >> bitSize);

        bitSize -= 8;
        if (pos >= bufSize) {
            flushBuffer();
        }
        buf[pos++] = (byte) (bits >> bitSize);

        int k = numberOfBits - 25;        // 1 <= k <= 7
        bits <<= k;                       // the missing k bits can now be added
        bits |= ((value >>> (32 - numberOfBits)) & ((1 << k) - 1));
        bitSize += k;                     // bitSize is updated

        if (bitSize >= 8) // 2 <= bitSize <= 15
        {
            bitSize -= 8;
            if (pos >= bufSize) {
                flushBuffer();
            }
            buf[pos++] = (byte) (bits >> bitSize);  // a byte is moved
        }
    } else {
        throw new IllegalArgumentException("Cannot write " + numberOfBits
                + " bits!");
    }

} // end writeBits 


public void writeLeftBits(int value) throws IOException {
    writeLeftBits(value, 32 - Integer.numberOfTrailingZeros(value));

} // end writeBits 

@Override
public void flush() throws IOException {
    if (bitSize > 0) {
        // the byte buffer is written to the ouput stream if it is full
        if (pos >= bufSize) {
            flushBuffer();
        }

        // 0-bits are added to create a full byte
        buf[pos++] = (byte) (bits <<= (8 - bitSize));
        bitSize = 0;
    }

    flushBuffer();
    out.flush();

} // end flush()


public int missingBits() throws IOException {
    if (out == null) {
        throw new IOException("The stream is closed!");
    }
    return bitSize == 0 ? 0 : 8 - bitSize;
}


@Override
protected void finalize() throws Throwable {
    super.finalize();
    if (out != null) {
        close();
    }
}

@Override
public void close() throws IOException {
    // a second call to close will have no effect
    if (out == null) {
        return;
    }
    flush();
    out.close();


    out = null;
    buf = null;
    pos = bufSize = -1;
    bitSize = 8;

} // end close()


public static String toBitString(byte[] b) {
    StringBuilder s = new StringBuilder();

    String[] fourBits = {"0000", "0001", "0010", "0011", "0100", "0101", "0110", "0111",
        "1000", "1001", "1010", "1011", "1100", "1101", "1110", "1111"};

    for (int c : b) {
        s.append(fourBits[(c & 255) >> 4]);
        s.append(fourBits[c & 15]);
        s.append(' ');
    }

    return s.toString();
}
} // end class BitOutputStream

3 个答案:

答案 0 :(得分:1)

我发现这个https://github.com/nayuki/Huffman-Coding/tree/master/src/nayuki/huffmancoding与你的霍夫曼编码有关。这可能很有用。

如果您可以提供 BitInputStream / BitOutputStream 类,我认为您的问题就在那里,可以根据您的代码提出更好的答案。

答案 1 :(得分:0)

我发现了这个问题,虽然我怀疑它有帮助,但你永远不会知道。

public void writeCompressed() throws IOException{ 
BitOutputStream fop2 = new BitOutputStream(
                new ObjectOutputStream(
                        new FileOutputStream(
                                "C:\\Users\\David\\Documents\\davidCompress.dabc")));
for (int i = 0; i < secuenciaFinal.length(); i++) {
    if (secuenciaFinal.charAt(i) == '1') {
        fop2.write1Bit();//lee la cadena y si contiene 1 escribe in 1 bit en mi archivo1
    } else if (secuenciaFinal.charAt(i) == '0') {
        fop2.write0Bit();//si la cadena contiene 0 bits escribe 0 bits
    } else {
        //fop2.missingBits();
    }
} 
fop2.close();        

}

问题在于写作方法。我唯一能做的就是将fop2的实例更改为:

 BitOutputStream fop2 = new BitOutputStream (
                    new FileOutputStream(
                            "C:\\Users\\David\\Documents\\davidCompress.dabc"));

答案 2 :(得分:0)

我创建了这个类:

package test.stackoverflow;

import java.io.FileInputStream;
import java.io.FileOutputStream;

/**
 *
 * @author Pasban
 */
public class MyBitBuffer {

    private StringBuffer sb;
    private int index = 0;

    public MyBitBuffer() {
        sb = new StringBuffer();
    }

    private void zero() {
        sb.append('0');
    }

    private void one() {
        sb.append('1');
    }

    @Override
    public String toString() {
        return sb.toString();
    }

    private void save(String filename) throws Exception {
        String all = sb.toString();
        int len = all.length();
        int leftover = 8 - len % 8;
        FileOutputStream fos = new FileOutputStream(filename);
        System.out.println("---------- Writing ----------");
        System.out.println("String view: " + sb.toString());
        fos.write(leftover);
        System.out.println("left-over: " + leftover);
        int k = 0;
        byte data = 0;
        for (int i = 0; i < len; i++) {
            data = (byte) (data << 1);
            if (all.charAt(i) == '1') {
                data += 1;
            }
            k++;
            if (k == 8) {
                fos.write(data);
                System.out.println("write-byte: " + data);
                data = 0;
                k = 0;
            }
        }
        if (leftover != 0) {
            System.out.println("write-byte: " + data); // last from left-over
            fos.write(data);
        }
        fos.close();
    }

    public static void main(String[] args) throws Exception {
        MyBitBuffer bb = new MyBitBuffer();
        bb.zero();
        bb.zero();
        bb.one();
        bb.zero();
        bb.one();
        bb.one();
        bb.one();
        bb.zero();
        bb.one();
        bb.one();
        bb.zero();
        bb.one();
        bb.one();
        bb.one();
        bb.zero();
        bb.save("hufman.test");

        MyBitBuffer cc = new MyBitBuffer();
        cc.load("hufman.test");
        cc.reset();
        int r;
        System.out.println("---------- Stream Read ----------");
        while ((r = bb.read()) != -1) {
            System.out.print(r);
        }
        System.out.println();
    }

    private void load(String filename) throws Exception {
        sb = new StringBuffer();
        FileInputStream fis = new FileInputStream(filename);
        System.out.println("---------- Reading ----------");
        int leftover = fis.read();
        System.out.println("left-over: " + leftover);
        int data;
        String str = "";
        while ((data = fis.read()) != -1) {
            System.out.println("read-byte: " + data);
            str = "";
            for (int i = 0; i < 8; i++) {
                if ((data & 1) == 1) {
                    str = '1' + str;
                } else {
                    str = '0' + str;
                }
                data = data >> 1;
            }
            sb.append(str);
        }
        if (leftover > 0) {
            sb.delete(sb.length() - 8, sb.length() - (8 - leftover));
        }
        fis.close();
        System.out.println("String view: " + sb.toString());
    }

    private void reset() {
        this.index = 0;
    }

    public int read() {
        if (index >= sb.length()) {
            return -1;
        }
        return (sb.charAt(index++) == '1') ? 1 : 0;
    }
}

这个类非常简单,它以位的形式读写数据。我不知道这是否有帮助。用法很简单。

实际大小为2字节,但是,我在文件头中添加一个0-8的数字,表示最后一个字节的长度。然后,在读取文件时,我从字符串的末尾删除了这个数量。注释该部分以在删除之前查看额外数据。

使用示例数据,总文件大小为(1 + 2 = 3)字节。

您可以将此类集成到您的代码中。