2016-08-25 4 views
2

今私は部分的にメッセージを効率的に分割しようとするちょっとしたルーチンを持っていて、計算にはOutputStream(通常BAOS)の文字を個別に追加してからbyte[] packed = packData(baos)のようなやり方でパックサイズからサイズを計算する必要があります。私がビットを無駄にしているので、この梱包ステップは必要ですbaos.write(my5bitbyte)。 、Javaには、例えば5ビットのデータを出力することができる組み込みのStreamやStreamがありますか?

  1. 各バイトからバイト
  2. を構築するための新しいビットセットを作成しますbaos.toByteArray()
  3. のバイトから設定ビットを取る:私は通常、このような何かを梱包段階でそう

    ビット0-4を取り出して、新しいビットセットに明らかな方法で追加します。

  4. 新しいビットセットからを最後のバイトの最後の7ビットに埋め込みます。

私の質問は次のとおりです。

BitOutputStreamなどの方法はありますか?または何か類似している?私が現在行っているやり方はややばかばかしいようですが、私は間違いなくもっと賢いかもしれませんが、すでに存在するものを見落としているかどうかは疑問です。

編集ByteArrayOutputStreamのソースを調べた後、それはすべてが、いくつかの凝っでカプセル化だけbyte[]なので、あなたがboolean[]を行う可能性があるため、それはいくつかBitArrayOutputStreamの正確な同じ方法で実施することができることは明らかと思われます。しかし、私はそれが存在するとは思わないので、私はそれをさらに調べるので、私の質問はその後になります...

これは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(); 
    } 
} 
+0

いいえ、最小単位のさまざまなプロトコル、デバイス、プロセッサ、RAMなどがバイトであるためです。あなたがいなくても、バイトをゼロで埋めることができます。すべてのビットが必要です。 –

+0

本当の質問は5ビットエンコーディングを使用する理由です。 Baudotは30年前にTelexのマシンと一緒に出かけました。 – EJP

+1

ByteArrayOutputStreamをラップしたカスタムFilterOutputStreamを使用して、それらを結合してBAOSに書き込むまでに受信したバイトをバッファリングするのはなぜでしょうか。 close()メソッドは最後の残りのビットがあればそれを埋め込み、それをBAOSに書き込み、BAOSを閉じます。 –

答えて

1

自然なアプローチは、その鎖(またはラップ)別々の出力ストリームクラス別の出力ストリーム(あなたは作家、バッファされたストリームとバッファリングされていないストリームをチェーンと同じように)書くことであろう。

コードはこれと似ています。私は完全なバイトに達するまで数ビットをバッファし、それを出力ストリームに書き込みます。私はそれをテストしていない。したがって、おそらくバグか2つが含まれている可能性があります。

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ビットを書き込むことができます。

関連する問題