我是编程新手,我尝试使用这种方法进行压缩,我已经具有正确的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

最佳答案

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

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

07-24 09:45