C#和Java中的hex到字节数组给出了不同的结果

首先,对于长篇文章感到抱歉,我想包括我的所有想法,以便你们更容易找到我的代码有什么问题。

我想将一个Hex字符串从C#应用程序传输到Java应用程序。 但是,当我在两种语言中将相同的hex值转换为字节数组时,输出是不同的。

例如,相同的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到字节数组的转换是不同的。 我认为Hexadecimal只是另一个基础上的数字。

谢谢您的帮助

Cydrick

更新

我通过使用以下代码替换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; } 

但是,当我在两种语言中将相同的hex值转换为字节数组时,输出是不同的。

你所看到的只是字节用Java签名而在C#中是无符号的。 因此,如果在Java中向任何负值添加256,您将获得C#中显示的值。 值中的实际是相同的 – 这只是顶部位是否被视为符号位的问题。

编辑:如注释中所述,如果您在调试器输出之外使用该字节作为整数,则可以始终使用:

 int someInt = someByte & 0xff; 

获取无符号值。

看起来这只是一个调试器问题。 您在Java调试器中看到的那些负值是您在C#调试器中看到的无符号值的等效符号。 例如,有符号字节-9 ==无符号字节247(注意它们总是相差256)。 数据很好。