gpt4 book ai didi

java - 在 Java 中,是否有一种内置的或常见的 Stream 允许输出,比如说,5 位数据?

转载 作者:行者123 更新时间:2023-11-30 10:39:53 25 4
gpt4 key购买 nike

现在我有一个小程序试图有效地将消息分成几部分,计算需要将字符单独附加到 OutputStream,通常是 BAOS,然后执行类似于 byte[] packed = packData(baos) 并根据打包大小计算大小。这个打包步骤是必要的,因为我在执行 baos.write(my5bitbyte) 时浪费了比特。

所以在打包步骤中我通常会做这样的事情:

  1. baos.toByteArray()
  2. 的字节中取出一个位集
  3. 为构造字节创建一个新的位集
  4. 从每个字节中取出位 0-4 并以明显的方式将它们附加到新的位集
  5. 从新的位集创建一个byte[],填充最后一个字节的最后一个最多 7 位

我的问题是:

是否有任何方式或诸如 BitOutputStream 之类的东西?或者类似的东西?我目前这样做的方式似乎相当愚蠢,我肯定可以更聪明地处理它,但我想知道我是否忽略了一些已经存在的东西。

编辑 在检查了 ByteArrayOutputStream 的源代码后,很明显它可以用完全相同的方式为某些 BitArrayOutputStream 实现,因为它这只是一个 byte[] 封装了一些奇特的东西,所以你可以做 boolean[]。但我认为它不存在,现在我进一步研究它,所以我的问题就变成了......

那么这是实现 BitArrayOutputStream 的合理方式吗?

class FixedLengthBitArrayOutputStream extends OutputStream {

private boolean[][] buffer;
private final int originalLength;
private final int bitLength;
private int position = 0;
private int expansions = 0;

FixedLengthBitArrayOutputStream(short bitLength, short length) {
this.buffer = new boolean[length][bitLength];
this.originalLength = length;
this.bitLength = bitLength;
}

private int limitBeforeExpansion(double factor) {
return Math.max(
(int) Math.floor(factor * buffer.length),
(int) Math.floor( (1 - Math.pow(factor, expansions + 1)) * buffer.length)
);
}

private boolean needsExpansion() {
return position > limitBeforeExpansion(0.8);
}

private void expandIfNecessary() {
if (needsExpansion()) {
expansions++;
this.buffer = Arrays.copyOf(this.buffer, (int) Math.pow((double)this.originalLength, expansions + 1));
}
}

public boolean[] bitValue(int number) throws IllegalStateException {

int remainder = number;
boolean[] bits = new boolean[this.bitLength];

for (int i = this.bitLength - 1; i >= 0; i--) {
int power = (int) Math.pow(2, i + 1);
boolean value = remainder > power;
bits[i] = value;
if (value) {
remainder -= power;
}
}

if (remainder != 0)
throw new IllegalStateException("whoa");

return bits;
}

@Override
public void write(int b) throws IOException, IllegalStateException {
expandIfNecessary();

this.buffer[position] = bitValue(b);
position++;
}

public byte[] toByteArray() {

BitSet bitSet = new BitSet(this.position * this.bitLength);

for (int i = 0; i < position; i++) {
boolean[] bits = this.buffer[i];

for (int j = 0; j < bits.length; j++) {
bitSet.set( i * bits.length + j , bits[j] );
}
}

return bitSet.toByteArray();
}
}

最佳答案

一种自然的方法是编写一个单独的输出流类来链接(或包装)另一个输出流(与链接编写器、缓冲流和非缓冲流的方式相同)。

代码可能与此类似。我缓冲了几位直到它达到一个完整的字节并将其写入输出流。我还没有测试过。因此它可能包含一两个错误。

class PackedBitsOutputStream {

private OutputStream outputStream;
private int numBufferedBits;
private byte bufferedBits;

PackedBitsOutputStream(OutputStream os) {
outputStream = os;
}

void writeBitSet(int data, int relevantBits) {
bufferedBits = (byte) (bufferedBits | (data << bufferedBits));
numBufferedBits += relevantBits;
if (numBufferedBits >= 8) {
outputStream.write(bufferedBits);
numBufferedBits -= 8;
bufferedBits = (byte) (data >> (relevantBits - numBufferedBits));
}
}

void flush() {
outputStream.write(bufferedBits);
bufferedBits = 0;
numBufferedBits = 0;
outputStream.flush();
}

void close() {
flush();
outputStream.close();
}
}

注意:writeBitSet 目前最多可以一次写入 8 位。

关于java - 在 Java 中,是否有一种内置的或常见的 Stream 允许输出,比如说,5 位数据?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39141806/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com