首页 > 解决方案 > 在 Java 中实现 writeBit 方法

问题描述

所以我知道在 Java 中你不能将单个位写到文件中,你必须使用 writeByte。我有一些理解,有一种方法可以实现 writeBit 方法,该方法通过在 8 个“位”连接在一起时调用 writeByte 来使用 writeByte。我希望像这样实现:

public void writeBit(char bit) {
    try {
    //functionality here
    } catch (IOException e) {
        System.out.println(e);
    }
}

但我似乎无法开始。我知道我可能应该有一些属性来跟踪我连接了多少位,但除此之外,我不知道如何实现这一点。

我想我的大问题是如何在不丢失连接的位字符串的情况下连续调用 writeBit,如果要使用 writeByte,writeBit 的实现会是什么样子?

作为旁注,如果不清楚,我在这里使用 DataOutputStream。

标签: javaencodingbinaryhuffman-codedataoutputstream

解决方案


我注意到有几个人讨论过使用两个实例变量,一个用于在向字节添加位时存储字节,另一个用于跟踪到目前为止已添加了多少位。虽然这是一个非常好的方法,但我想说明为什么您不需要第二个实例变量。

理论

无需跟踪到目前为止添加了多少位。我们需要的唯一信息是“字节是否已填充?”。不要将字节初始化为 0,而是尝试将其初始化为值 1。然后每次添加位时,将字节的位向左移动一个位置(使用位移运算符<<),然后将新位添加到最右边的地方。

在实践中,它看起来像这样,X新添加的位在哪里:

将字节初始化为值 1:00000001

要插入新位,请将位左移:00000010

X并在最右边的地方添加新的位:0000001X

左移:000001X0

添加新位:000001XX

最终,你会从你的方法中写入 7 位,最左边的位是11XXXXXXX

因此,在您的方法中,您可以检查每次调用时是否设置了最左边的位。如果是,那么您知道您已准备好在此迭代中将字节写入文件。你会先做同样的事情,左移然后添加新的位,所以现在你有了XXXXXXXX. 然后您将现在已满的字节写入文件,然后将字节重置为值 1,以便循环重新开始。

编写代码

首先,您需要一个实例变量来跟踪这些位。它需要是字节类型,我就叫它buffer

要将位向左移动一位,我们可以使用位移运算符,<<. 而且,为了让我们的生活更轻松,甚至还有一个移位赋值运算符 ,<<=因此我们可以在一次操作中执行移位并将新值赋回变量。这给我们留下了:

buffer <<= 1;

我们需要做的下一件事是添加新位。如果您将一个值与 1 进行或运算,则将设置最右边的位,而其余位将不受影响。如果您将值与 0 进行或运算,则不会影响任何位。如果新位为 1,我们可以使用此技巧仅设置最右边的位(The|=是 OR 赋值运算符):

buffer |= bit ? 1 : 0;

然后,这段代码的最后一段是编写 if 语句来检查是否设置了最左边的位。如果是,那么当我们将它与 进行 AND 时10000000,我们将得到10000000。如果没有,我们将得到00000000. 10000000128十进制的(or -128, or 256, 都可以),所以我们的表达式是:

(buffer & 128) == 128

结果

将所有这些部分放在一起,我们得到:

// Notice bit is type boolean
public void writeBit(boolean bit) {
    // If the leftmost bit in buffer is set:
    if ((buffer & 128) == 128) {

        // Shift all the bits in buffer to the left 1 place
        buffer <<= 1;

        // Add the new bit in the rightmost place
        buffer |= bit ? 1 : 0;

        // Write the now-full byte to the file
        // I'm just calling your DataOutputStream "dos" here
        try {
            dos.writeByte(buffer);
        } catch (IOException e) {
            throw new RuntimeException();
        }

        // Reset buffer to a value of 1
        buffer = 1;
    } else {
        // Shift all the bits in buffer to the left 1 place
        buffer <<= 1;

        // Add the new bit in the rightmost place
        buffer |= bit ? 1 : 0;
    }
}

推荐阅读