1

CCRC16 メソッドをに変換する必要がありJavaます。C問題は、私がバイト操作が苦手なことです。

Cコード:

static const unsigned short crc16_table[256] =
{
 0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,
 ...  /* Removed for brevity */
 0x8201,0x42C0,0x4380,0x8341,0x4100,0x81C1,0x8081,0x4040
};

unsigned short crc16 (const void *data, unsigned data_size)
{
 if (!data || !data_size)
 return 0;
 unsigned short crc = 0;
 unsigned char* buf = (unsigned char*)data;
 while (data_size--)
 crc = (crc >> 8) ^ crc16_table[(unsigned char)crc ^ *buf++];
 return crc;
}

そして、それはそれを変換する私の試みです。それが正しいかどうかはわかりません。

private static int[] table = {
    0x0000,0xC0C1,0xC181,0x0140,0xC301,0x03C0,0x0280,0xC241,0xC601,0x06C0,0x0780,0xC741,
    ...    // Removed for brevity
    0x4400,0x84C1,0x8581,0x4540,0x8701,0x47C0,0x4680,0x8641,0x8201,0x42C0,0x4380,0x8341, 0x4100,0x81C1,0x8081,0x4040
};

public static int getCode (String[] data){
    if (data.length == 0) {
        return 0;
    }
    int crc = 0;
    for (String item : data) {
        byte[] bytes = item.getBytes();
        for (byte b : bytes) {
            crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff]; //this confuses me
        }
    }
    return crc;
}

質問: 私の Java への移植は正しいですか?


編集

変更されcrc16た作業方法 (素晴らしい回答に感謝):

public static int getCode(String data) {
    if (data == null || data.equals("")) {
        return 0;
    }
    int crc = 0x0000;
    byte[] bytes = data.getBytes();
    for (byte b : bytes) {
        crc = (crc >>> 8) ^ table[(crc ^ b) & 0xff];
    }
    return crc;
}

これは Decimal 値を返します。また、CRC16 コードは 16 進数である必要があります。このメソッドを使用して、base 16 に変換しました。受信したcrcように実行しdec2m(crc, 16)ます。

static String dec2m(int N, int m) {
    String s = "";
    for (int n = N; n > 0; n /= m) {
        int r = n % m;
        s = r < 10 ? r + s : (char) ('A' - 10 + r) + s;
    }
    return s;
}

結果をテストするには、このサイトを使用できます(@greenaps に感謝)

4

2 に答える 2

2

Mohit Jainが言ったように、あなたが書いたものはよさそうです。しかし、あなたの関数は元の C の関数とは異なる動作をします: String の配列を受け取りますが、C コードは void * とバイト単位の長さを取ります。したがって、変換関数を使用して、UTF-8 と Latin1 プラットフォームの間で非 ASCII 文字を含む文字列を検証すると、異なる結果が得られます。Latin1 では、「éè」は 2 バイトを与えるためです0xe9。、0xe84バイトを取得します:、、、0xc3= > CRC関数は異なる結果を返します。0xa90xc30xa8

私見、元のコードに固執し、バイト配列のCRCのみを計算する必要があります。常に同じ文字セット (たとえば UTF-8 など) を強制することもできますが、結果を C 実装と比較することは依然として難しく、生のバイト配列 (バイナリ データ) の CRC を計算する能力が失われます。

とにかく、実装が元の C のものと同じ結果をもたらすことを確認する唯一の方法は、任意のバイト文字列 (たとえば、0 から 255 までのすべてのバイト) を取得し、それを一方の C ルーチンと Java に渡すことです。 1 つを反対側に置き、両方の CRC を比較します。

于 2015-06-17T12:28:16.890 に答える
1

Cコードの関数呼び出しをcrc16 (const void *data, unsigned data_size)間違って翻訳しました。

public static int getCode (String[] data)

する必要があります

public static int getCode (String data)

getCode (String)さらに、 Wialon pdf では、ではなくが必要であることも確認できますgetCode(String[])

受け取った文字列をバイト配列に変換することは成り立ちます。

于 2015-06-18T08:22:21.633 に答える