2012-04-24 7 views
0

私は、各ペイロードバイトのMSBをMSBコレクションバイト(septett)に抽出し、受信側にMSBを再注入するバイナリプロトコルを持っています。ペイロードは、n個の4バイトフレームで構成され、送信側(私の場合は6個)に応じて配置されます。MSBが削除/復元されるようにバイト値を変換する

ワイヤーに見られるように、これらの2つの例示的なフレームは、そのseptett(最後のバイト)と、次のとおりのMSBを再注入して、

0x2E 0x00 0x5F 0x00 0x04 
0x79 0x01 0x38 0x22 0x04 

それらが同じフレーム、クライアント側である:

0x2E 0x00 0xDF 0x00 
0x79 0x01 0xB8 0x22 

変換を行うC関数は、this documentの9および10ページで定義されています。私のこれらのバージョンは、Javaで以下のとおりです。私が持っている問題は、この作品のどれもが動作しないことです、なぜ私は混乱しています。私はワイヤーから4バイトを渡し、同じバイトを手に入れて、そのままにします。私はここで何が間違っているかを理解する助けをすることができました。 Javaでは

private static byte[] vbusExtractSeptett(byte[] data, int offset, int length) { 
    byte septett = 0; 
    for (int i = 0; i < length; i++) { 
     if ((data[offset + i] & 0x80) != 0) { 
      data[offset + i] &= 0x7F; 
      septett |= 1 << i; 
     } 
    } 

    data[offset + length] = septett; 
    return data; 
} 

private static byte[] vbusInjectSeptett(final byte[] data, int offset, int length) { 
    byte septett = data[offset + length]; 

    for (int i = 0; i < length; i++) { 
     if ((septett & (1 << i)) != 0) 
      data[offset + i] |= 0x80; 
    } 

    return data; 
} 

答えて

1

、バイトを署名されています。あなたのコードをすべて読まなくても、それが問題だと思います。

文書のCコードでは、符号なしchar演算が使用されています。

Javaには「符号なし」がないため、おそらくすべての計算をshort(またはint)で行い、次にバイトに変換する必要があります。符号ビットをマスクしてください。何かのように

byte theResult = theIntIDidtheMathOn & 0xFF; 
data[index] = theResult; 
0

他の答えは正しいです、あなたは署名されたバイトのJavaの使用を考慮していません。

これを解決するためのいくつかの可能性があります:あなたは「&の0xFF」で上記のものを行うことができます

  1. (私は以下の行ったように)あなたはint型としてすべてを扱うことができ
  2. あなたは図書館を利用することができます。いくつかの例は、JOOU(この符号なしタイプの不足に応じて開始されたもの)またはnetty channelbuffers(NB:nettyはソケットなどのようにネットワークIOに焦点を当てていますが、そのチャネルバッファクラスはバイトストリームと符号付き/あなたが扱っているようなバイナリプロトコルを変換するためにかなり多く使用しています)。

私は以下の質問に「解決策」を書いています。私はあなたのために持っているでしょう

public class SOAnswer 
{ 
    private static void vbusExtractSeptett(int[] data, int offset, int length) { 
     int septett = 0; 

     for (int i = 0; i < length; i++) { 
      if ((data[offset + i] & 0x80) != 0) { 
       data[offset + i] &= 0x7F; 
       septett |= 1 << i; 
      } 
     } 

     data[offset + length] = septett; 
    } 

    private static void vbusInjectSeptett(final int[] data, int offset, int length) { 
     int septett = data[offset + length]; 

     for (int i = 0; i < length; i++) { 
      if ((septett & (1 << i)) != 0) 
       data[offset + i] |= 0x80; 
     } 

     // clear the septett byte 
     data[offset + length] = 0x00; 
    } 

    private static void printIntArrayAsHEX(int[] array) 
    { 
     StringBuilder builder = new StringBuilder(); 

     for (int a : array) 
     { 
      String s = Integer.toHexString(a); 
      if (s.length() == 1) 
       builder.append("0"); 
      builder.append(s + ":"); 
     } 

     builder.substring(0, builder.lastIndexOf(":") - 1); 

     System.out.println(builder.toString()); 
    } 

    public static void main(String[] args) 
    { 
     // Create an array long enough for the extracting/injecting 
     int[] arr = new int[]{0x2E, 0x00, 0xDF, 0x00, 0x00}; 
     // see what it looks like 
     printIntArrayAsHEX(arr); 

     // perform extraction 
     vbusExtractSeptett(arr, 0, 4); 
     // see what it looks like 
     printIntArrayAsHEX(arr); 

     // Perform injection 
     vbusInjectSeptett(arr, 0, 4); 
     // see what it looks like 
     printIntArrayAsHEX(arr); 
    } 
} 

一つの推薦はあなたが本当にしてそのままCコード(プリミティブ型の配列を渡すの特に非常に機能的なプログラミングスタイルへのオフセットを再実装する場合を考えることです配列と配列の長さ)。たぶんこのようなものはもっと多くなるでしょう:

private static int[] vbusExtractSeptettJAVASTYLE(int[] data) { 
    int[] extractedData = Arrays.copyOf(data, data.length +1); 

    int septett = 0; 

    for (int i = 0; i < data.length; i++) { 
     if ((data[i] & 0x80) != 0) { 
      extractedData[i] = data[i] &= 0x7F; 
      septett |= 1 << i; 
     } 
    } 

    extractedData[extractedData.length-1] = septett; 

    return extractedData; 
} 
関連する問題