4

まず第一に、長い投稿で申し訳ありません。コードの何が問題なのかを簡単に見つけられるように、私の考えをすべて含めたいと思います。

C# アプリケーションから Java アプリケーションに Hex 文字列を転送したいと考えています。しかし、両方の言語で同じ 16 進値をバイト配列に変換すると、出力が異なります。

たとえば、同じ Hex 値は次のようになります。

  [101, 247, 11, 173, 46, 74, 56, 137, 185, 38, 40, 191, 204, 104, 83, 154]

C# および

  [101, -9, 11, -83, 46, 74, 56, -119, -71, 38, 40, -65, -52, 104, 83, -102]

Javaで

C# で使用するメソッドは次のとおりです。

public static string ByteArrayToHexString(byte[] byteArray)
{
    return BitConverter.ToString(byteArray).Replace("-",""); //To convert the whole array
}

public static byte[] HexStringToByteArray(string hexString)
{

    byte[] HexAsBytes = new byte[hexString.Length / 2];
    for (int index = 0; index < HexAsBytes.Length; index++)
    {
        string byteValue = hexString.Substring(index * 2, 2);
        HexAsBytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
    }

    return HexAsBytes;
}

そしてJavaのもの:

 public static String ByteArrayToHexString(byte[] bytes) {
     StringBuilder builder = new StringBuilder();
     for (byte b: bytes) {
     builder.append(String.format("%02x", b));
     }
     return builder.toString().toUpperCase();
 }

 public static byte[] HexStringToByteArray(String s) {
    int len = s.length();
    byte[] data = new byte[len / 2];
    for (int i = 0; i < len; i += 2) {
        data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                             + Character.digit(s.charAt(i+1), 16));
    }
    return data;
}

C# での例を次に示します。

        String hexString = "65F70BAD2E4A3889B92628BFCC68539A";
        byte[] byteArray = HexBytes.HexStringToByteArray(hexString);
        //Using the debugger, byteArray = [101, 247, 11, 173, 46, 74, 56, 137, 185, 38, 40, 191, 204, 104, 83, 154]
        String hexString2 = HexBytes.ByteArrayToHexString(byteArray)
        Console.Write("HEX: " + hexString2);
        //Outputs 65F70BAD2E4A3889B92628BFCC68539A

Java での例:

    String hexString = "65F70BAD2E4A3889B92628BFCC68539A";
    byte[] byteArray = HexBytes.HexStringToByteArray(hexString);
    //Using the debugger, byteArray = [101, -9, 11, -83, 46, 74, 56, -119, -71, 38, 40, -65, -52, 104, 83, -102]
    String hexString2 = HexBytes.ByteArrayToHexString(byteArray);
    System.out.println("HEX: " + hexString2);
    //Outputs 65F70BAD2E4A3889B92628BFCC68539A

ご覧のとおり、逆の操作を行うと、最終的な Hex 値は最初の値と等しくなります。これは、変換方法が両方の言語で個別に適切である可能性があることを意味します。しかし、Hex からバイト配列への変換が両方の言語で異なる理由がわかりません。16 進数は単に別の基数の数値だと思っていました。

助けてくれてありがとう

シドリック

アップデート

C# コードを次のコードに置き換えることで、この問題を修正しました。

public static string ByteArrayToHexString(sbyte[] byteArray)
{
    return BitConverter.ToString(convert(byteArray)).Replace("-", ""); //To convert the whole array
}

public static sbyte[] HexStringToByteArray(string hexString)
{

    byte[] HexAsBytes = new byte[hexString.Length / 2];
    for (int index = 0; index < HexAsBytes.Length; index++)
    {
        string byteValue = hexString.Substring(index * 2, 2);
        HexAsBytes[index] = byte.Parse(byteValue, NumberStyles.HexNumber, CultureInfo.InvariantCulture);
    }

    return convert(HexAsBytes);
}


private static sbyte[] convert(byte[] byteArray)
{
    sbyte[] sbyteArray = new sbyte[byteArray.Length];
    for (int i = 0; i < sbyteArray.Length; i++)
    {
        sbyteArray[i] = unchecked((sbyte) byteArray[i]);
    }

    return sbyteArray;
}

private static byte[] convert(sbyte[] sbyteArray)
{
    byte[] byteArray = new byte[sbyteArray.Length];
    for (int i = 0; i < byteArray.Length; i++)
    {
        byteArray[i] = (byte) sbyteArray[i];
    }
    return byteArray;
}
4

2 に答える 2

10

しかし、両方の言語で同じ 16 進値をバイト配列に変換すると、出力が異なります。

表示されているのは、Java ではバイトが署名され、C# では署名されていないことだけです。したがって、Java で負の値に 256 を追加すると、C# で示される値が得られます。値の実際のビットは同じです。最上位ビットが符号ビットとして扱われるかどうかの問題です。

編集:コメントに記載されているように、バイトをデバッガ出力の外で整数として使用している場合は、いつでも使用できます:

int someInt = someByte & 0xff;

符号なし値を取得します。

于 2013-06-04T16:19:08.517 に答える
1

これはデバッガーのみの問題のようです。Java デバッガーに表示されるこれらの負の値は、C# デバッガーに表示される符号なしの値に相当する符号付きです。たとえば、符号付きバイト -9 == 符号なしバイト 247 (常に 256 だけ異なることに注意してください)。データは問題ありません。

于 2013-06-04T16:20:11.493 に答える