2012-02-01 7 views
0

バイトの特定の範囲が異なるデータを表すバイトストリームを送受信しようとしています。単一のプリミティブデータ型をバイトに変換する方法を見つけましたが、特定のバイト領域に特定のデータを配置する簡単な方法があるかどうかは疑問です。混在型のバイト配列を取り込むための現在の最良の方法

例えば、私は次のようなものを作るか、読むために必要がある場合があります。

byte 1 - int 
byte 2-5 - int 
byte 6-13 - double 
byte 14-21 - double 
byte 25 - int 
byte 26-45 - string 

任意の提案をいただければ幸いです。

+0

私は整数と倍精度の通常のサイズの答えを与えました。整数をByteBufferに格納し、サイズを縮小し、最初のバイトが実際にゼロであるかどうかをチェックしたり、データを失いたい場合は、最後のバイト数(4のバイト数)を取得できます。これはダブルスの方が難しくなります。ダウンサイジングしたい場合は独自のフォーマットを作成しなければならず、プロセス中のpreciousを失うかもしれません。 –

+0

私はついにスペック・プロバイダにデータ長を対応するJavaプリミティブに制限するよう説得しました。私たちは、ByteBuffer内の操作にマップされていなかった2バイトの浮動小数点を使いたいという問題にぶつかって、私たちの側でそれを試してサポートするよりも、変更を加える方が簡単だと決めました。 –

答えて

1

DataOutputStream/DataInputStream、または配列の場合はByteBufferクラスを試してください。

整数をXバイトで格納する場合は、次の方法を使用できます。名前が悪いと思われる場合は、いくつかの(暗号化)アルゴリズムの説明で使用されている、あまり説明的ではないi2osという名前を使用することができます。返されたオクテット文字列は、あなたのプロトコルに指定する必要があるunsigned intのBig Endianエンコーディングを使用することに注意してください。

public static byte[] possitiveIntegerToOctetString(
     final long value, final int octets) { 
    if (value < 0) { 
     throw new IllegalArgumentException("Cannot encode negative values"); 
    } 

    if (octets < 1) { 
     throw new IllegalArgumentException("Cannot encode a number in negative or zero octets"); 
    } 

    final int longSizeBytes = Long.SIZE/Byte.SIZE; 
    final int byteBufferSize = Math.max(octets, longSizeBytes); 
    final ByteBuffer buf = ByteBuffer.allocate(byteBufferSize); 
    for (int i = 0; i < byteBufferSize - longSizeBytes; i++) { 
     buf.put((byte) 0x00); 
    } 
    buf.mark(); 
    buf.putLong(value); 

    // more bytes than long encoding 
    if (octets >= longSizeBytes) { 
     return buf.array(); 
    } 

    // less bytes than long encoding (reset to mark first) 
    buf.reset(); 
    for (int i = 0; i < longSizeBytes - octets; i++) { 
     if (buf.get() != 0x00) { 
      throw new IllegalArgumentException("Value does not fit in " + octets + " octet(s)"); 
     } 
    } 

    final byte[] result = new byte[octets]; 
    buf.get(result); 
    return result; 
} 

EDITの文字列を保存する前に、パディングメカニズム(スペースが最も使用される)と考えられ、文字エンコーディングなどが考えられます。 String.getBytes(Charset.forName("ASCII"))または"Latin-1"。これらは、1文字あたり1バイトの最も一般的なエンコードです。 「UTF-8」のサイズを計算するのは少し困難です(最初にエンコードし、最後に0x32のバイトを追加します(ByteBufferを使用)。

0

データ型ごとに一定のサイズがあると考えるとよいでしょう。たとえば、32ビットのJava intは4バイトをとり、長さは8バイトなどとなります。実際には、JavaのDataInputStreamとDataOutputStreamを使用すると、基本的にはそれが実行されます。彼らはread/writeIntのような実際に素晴らしいメソッドを持っています。

関連する問題