Прямо сейчас у меня есть небольшая процедура, которая пытается эффективно сегментировать сообщение на части, а для вычисления требуется добавить символы отдельно к OutputStream
, обычно BAOS
, а затем делать что-то вроде byte[] packed = packData(baos)
и вычислять размер из упакованного размера. Этот шаг упаковки необходим, потому что я теряю биты, когда я делаю baos.write(my5bitbyte)
.В Java есть встроенный или общий вид Stream, который позволяет выводить, скажем, 5-битные данные?
Так на стадии упаковки, я обычно что-то вроде этого:
- Возьмите немного набор из байтов
baos.toByteArray()
- сделать новый бит набор для построения байт
- Из каждого байта, возьмите биты 0-4 и добавьте их очевидным образом к новому набору бит
- Сделайте
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();
}
}
Нет, поскольку самый маленький блок различных протоколов, устройств, процессоров, баранов и т. Д. - это байт. Вы можете просто поместить байты с нулями, если не хотите, нужны все биты –
Реальный вопрос: почему вы используете 5-битную кодировку. Баудо вышел с аппаратами Телекса 30 лет назад. – EJP
Почему бы не использовать собственный фильтр FilterOutputStream, который будет обертывать ваш ByteArrayOutputStream и который будет буферизовать полученные байты, пока они не будут объединены вместе и записаны в BAOS. Метод close() будет заполнять последние оставшиеся биты, если они есть, записать их в BAOS и закрыть BAOS. –