4

我正在做一个学校作业(做霍夫曼编码),我需要某种位缓冲区来放入所有位。虽然我确实在谷歌上发现了几件事,但大部分东西都是垃圾 - 没有编译,引用了我没有的其他库等。有没有人有一个真正好的位缓冲类?我真正想做的就是一次读取和写入一个位。如果没有人有好的数据结构,是否有一些现有的数据结构可以有效地保存我自己可以用来编写的那种数据?

4

3 回答 3

2

我在解决霍夫曼代码实现时遇到了同样的问题,我使用了这个库并对其进行了测试,它可以工作..

位输出流

    import java.io.*;

/**
 * Write bits-at-a-time where the number of bits is between 1 and 32.
 * Client programs must call <code>flush</code> or
 * <code>close</code> when finished writing or not all bits will be written.
 * This class is intended to be used with <code>BitInputStream</code> to
 * facilitate reading and writing data in a bits-at-a-time manner.
 * <P>
 * Updated for version 2.0 to extend java.io.OutputStream
 * <P>
 * Any exceptions generated are rethrown as <code>RuntimeException</code> objects
 * so client code does not have to catch or rethrow them.
 * <P>
 * @author Owen Astrachan
 * @version 1.0, July 2000
 * @version 2.0, October 2004
 * @version 2.1, March 2010, Fixed >> to >>> bug in writeBits
 */


public class BitOutputStream extends OutputStream
{


    private OutputStream  myOutput;
    private int           myBuffer;
    private int           myBitsToGo;

    private static final int bmask[] = {
        0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,
        0x1ff,0x3ff,0x7ff,0xfff,0x1fff,0x3fff,0x7fff,0xffff,
        0x1ffff,0x3ffff,0x7ffff,0xfffff,0x1fffff,0x3fffff,
        0x7fffff,0xffffff,0x1ffffff,0x3ffffff,0x7ffffff,
        0xfffffff,0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff
    };

    private static final int BITS_PER_BYTE = 8;

    /**
     * Required by OutputStream subclasses, write the low
     * 8-bits to the underlying outputstream
     */
    public void write(int b) throws IOException {
        myOutput.write(b);
    }

    /**
     * Create a stream that writes-through to the <code>OutputStream</code> object
     * passed as a parameter.
     * @param out is the output stream to which bits are written
     */
    public BitOutputStream(OutputStream out){
        myOutput = out;
        initialize();
    }

    private void initialize(){
        myBuffer = 0;
        myBitsToGo = BITS_PER_BYTE;
    }
    /**
     * Construct a bit-at-a-time output stream with specified file
     * name.
     * @param filename is the name of the file being written
     * @throws RuntimeException if opening file fails for either FileNotFound
     * or for Security exceptoins
     */
    public BitOutputStream(String filename)
    {
        try{
            myOutput = new BufferedOutputStream(new FileOutputStream(filename)); 
        }
        catch (FileNotFoundException fnf){
            throw new RuntimeException("could not create " + filename + " " + fnf);
        }
        catch(SecurityException se){
            throw new RuntimeException("security exception on write " + se);
        }
        initialize();
    }


    /**
     * Flushes bits not yet written, must be called by client
     * programs if <code>close</code> isn't called.
     * @throws RuntimeException if there's a problem writing bits
     */
    public void flush()
    {
        if (myBitsToGo != BITS_PER_BYTE) {
            try{
                write( (myBuffer << myBitsToGo) );
            }
            catch (java.io.IOException ioe){
                throw new RuntimeException("error writing bits on flush " + ioe);
            }
            myBuffer = 0;
            myBitsToGo = BITS_PER_BYTE;
        }

        try{
            myOutput.flush();    
        }
        catch (java.io.IOException ioe){
            throw new RuntimeException("error on flush " + ioe);
        }
    }

    /**
     * Releases system resources associated with file and
     * flushes bits not yet written. Either this function
     * or flush must be called or not all bits will be written
     * @throws RuntimeException if close fails
     */
    public void close()
    {
        flush();
        try{
            myOutput.close();
        }
        catch (IOException ioe){
            throw new RuntimeException("error closing BitOutputStream " + ioe);
        }
    }

    /**
     * Write specified number of bits from value to a file.
     * @param howManyBits is number of bits to write (1-32)
     * @param value is source of bits, rightmost bits are written
     * @throws RuntimeException if there's an I/O problem writing bits
     */

    public void writeBits(int howManyBits, int value)
    {
        value &= bmask[howManyBits];  // only right most bits valid

        while (howManyBits >= myBitsToGo){
            myBuffer = (myBuffer << myBitsToGo) |
                       (value >>> (howManyBits - myBitsToGo));
            try{
                write(myBuffer);    
            }
            catch (java.io.IOException ioe){
                throw new RuntimeException("error writing bits " + ioe);
            }

            value &= bmask[howManyBits - myBitsToGo];
            howManyBits -= myBitsToGo;
            myBitsToGo = BITS_PER_BYTE;
            myBuffer = 0;
        }

        if (howManyBits > 0) {
            myBuffer = (myBuffer << howManyBits) | value;
            myBitsToGo -= howManyBits;
        }
    }
}

位输入流

import java.io.*;

/**
 * Reads bits-at-a-time where the number of bits is between 1 and 32.
 * Updated for version 2.0 to extend java.io.InputStream. This class
 * can be used together with <code>BitOutputStream</code> to facilitate
 * reading and writing data several bits-at-a-time. BitInputStream objects
 * that are constructed from a File support <code>reset()</code>. However,
 * if constructed from an <code>InputStream</code> an object cannot be reset.
 * <P>
 * Any exceptions generated are rethrown as <code>RuntimeException</code> objects
 * so client code does not have to catch or rethrow them. (Unless the extension
 * of <code>InputStream</code> requires throwing as another type of exception, e.g.,
 * as with method <code>read</code>.
 * <P>
 * @author Owen Astrachan
 * @version 1.0, July 2000
 * @version 2.0, October 2004
 */

public class BitInputStream extends InputStream
{
    private InputStream     myInput;
    private int             myBitCount;
    private int             myBuffer;
    private File            myFile;

    private static final int bmask[] = {
        0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff,
        0x1ff,0x3ff,0x7ff,0xfff,0x1fff,0x3fff,0x7fff,0xffff,
        0x1ffff,0x3ffff,0x7ffff,0xfffff,0x1fffff,0x3fffff,
        0x7fffff,0xffffff,0x1ffffff,0x3ffffff,0x7ffffff,
        0xfffffff,0x1fffffff,0x3fffffff,0x7fffffff,0xffffffff
    };

    private static final int BITS_PER_BYTE = 8;
    /**
     * Construct a bit-at-a-time input stream from a file whose
     * name is supplied. 
     * @param filename is the name of the file that will be read.
     * @throws RuntimeException if filename cannot be opened.
     */
    public BitInputStream(String filename)
    {
        this(new File(filename));
    }

    /**
     * Construct a bit-at-a-time input stream from <code>file</code>.
     * @param file is the File that is the source of the input
     * @throws RuntimeExceptoin if file cannot be opened.
     */
    public BitInputStream(File file)
    {
        myFile = file;  
        try {
            reset();
        } catch (IOException e) {
            throw new RuntimeException("could not open file for reading bits "+e);
        }

    }

    /**
     * Open a bit-at-a-time stream that reads from supplied InputStream. If this
     * constructor is used the BitInputStream is not reset-able.
     * @param in is the stream from which bits are read.
     */
    public BitInputStream(InputStream in){
        myInput = in;
        myFile = null;
    }

    /**
     * Return true if the stream has been initialized from a File and
     * is thus reset-able. If constructed from an InputStream it is not reset-able.
     * @return true if stream can be reset (it has been constructed appropriately from a File).
     */
    public boolean markSupported(){
        return myFile != null;
    }

    /**
     * Reset stream to beginning. The implementation creates a new
     * stream.
     * @throws IOException if not reset-able (e.g., constructed from InputStream).
     */

    public void reset() throws IOException
    {
        if (! markSupported()){
            throw new IOException("not resettable");
        }
        try{
            close();
            myInput = new BufferedInputStream(new FileInputStream(myFile));
        }
        catch (FileNotFoundException fnf){
            System.err.println("error opening " + myFile.getName() + " " + fnf);
        }
        myBuffer = myBitCount = 0;
    } 

    /**
     * Closes the input stream.
     * @throws RuntimeException if the close fails
     */

    public void close()
    {
        try{
            if (myInput != null) {
                myInput.close();
            }
        }
        catch (java.io.IOException ioe){
           throw new RuntimeException("error closing bit stream " + ioe);
        }
    }

    /**
     * Returns the number of bits requested as rightmost bits in
     * returned value, returns -1 if not enough bits available to
     * satisfy the request.
     *
     * @param howManyBits is the number of bits to read and return
     * @return the value read, only rightmost <code>howManyBits</code>
     * are valid, returns -1 if not enough bits left
     */

    public int readBits(int howManyBits) throws IOException
    {
        int retval = 0;
        if (myInput == null){
            return -1;
        }

        while (howManyBits > myBitCount){
            retval |= ( myBuffer << (howManyBits - myBitCount) );
            howManyBits -= myBitCount;
            try{
                if ( (myBuffer = myInput.read()) == -1) {
                    return -1;
                }
            }
            catch (IOException ioe) {
                throw new IOException("bitreading trouble "+ioe);
            }
            myBitCount = BITS_PER_BYTE;
        }

        if (howManyBits > 0){
            retval |= myBuffer >> (myBitCount - howManyBits);
            myBuffer &= bmask[myBitCount - howManyBits];
            myBitCount -= howManyBits;
        }
        return retval;
    }

    /**
     * Required by classes extending InputStream, returns
     * the next byte from this stream as an int value.
     * @return the next byte from this stream
     */
    public int read() throws IOException {
        return readBits(8);
    }
}
于 2014-03-27T12:28:00.817 回答
0

在此处查找位缓冲区示例

http://www.javadocexamples.com/java_source/com/sun/java/help/search/BitBuffer.java.html

于 2012-11-14T19:17:53.697 回答
-2

一般来说,队列是一个很好的缓冲区(FIFO)。可以使用布尔值来表示位。Java 库中的 Queue 实现是通用的,因此您可以像这样实例化您的位缓冲区:

Queue<Boolean> bbuff = new Queue<Boolean>();
Boolean imabit = false;

你像这样排队/缓冲位:

bbuff.add(imabit);

然后你出列/读取(并删除)下面的位,如下所示:

Boolean dequeuedbit = bbuff.remove();
于 2012-11-14T19:17:21.547 回答