C#和Java中的十六进制到字节数组给出不同的结果 [英] Hex to Byte Array in C# and Java Gives Different Results

查看:157
本文介绍了C#和Java中的十六进制到字节数组给出不同的结果的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

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



例如,相同的十六进制值给出

  [101, 24,7,11,173,46,74,56,137,185,38,40,41,204,104,83,154] 

在C#和

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

in Java



以下是我在C#中使用的方法:

  public static string ByteArrayToHexString(byte [] byteArray)
{
return BitConverter.ToString(byteArray).Replace( - ,); //转换整个数组
}

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);
}

返回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]; (int i = 0; i data [i / 2] =(byte)((Character.digit(s.charAt(i),16 )< 4)
+ Character.digit(s.charAt(i + 1),16));
}
返回数据;

$ / code>

下面是C#中的一个例子:

 字符串hexString =65F70BAD2E4A3889B92628BFCC68539A; 
byte [] byteArray = HexBytes.HexStringToByteArray(hexString);
//使用调试器,byteArray = [101,247,11,173,46,74,56,137,185,38,40,191,204,104,83,154]
字符串hexString2 = HexBytes.ByteArrayToHexString(byteArray)
Console.Write(HEX:+ hexString2);
//输出65F70BAD2E4A3889B92628BFCC68539A

以及Java中的一个示例:

 字符串hexString =65F70BAD2E4A3889B92628BFCC68539A; 
byte [] byteArray = HexBytes.HexStringToByteArray(hexString);
//使用调试器,byteArray = [101,-9,11,-83,46,74,56,-119,-71,38,40,-65,-52,104,83, - 102]
字符串hexString2 = HexBytes.ByteArrayToHexString(byteArray);
System.out.println(HEX:+ hexString2);
//输出65F70BAD2E4A3889B92628BFCC68539A

正如你所看到的,当我做相反的操作时,最终的十六进制值等于第一个,这意味着我转换的方式在两种语言中都可能很好。但我不明白为什么在这两种语言中从十六进制到字节数组的转换是不同的。我认为十六进制只是另一个基础上的数字。



感谢您的帮助

Cydrick



更新



通过用以下代码替换C#代码解决了此问题: (byteArray)


$ pre $ public static string ByteArrayToHexString(sbyte [] byteArray)
{
return BitConverter.ToString(convert(byteArray) ).Replace( - ,); //转换整个数组
}

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);


$ b $ 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];
}
返回byteArray;
}


解决方案


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


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



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

  int someInt = someByte& 0xFF的; 

得到无符号值。


First of all, sorry for the long post, I want to include all my thoughts so it's easier for you guys to find what's wrong about my code.

I want to transfer an Hex string from a C# application to a Java application. But, when I convert the same Hex value to a Byte Array on both languages, the output is different.

For instance, the same Hex value gives

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

in C# and

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

in Java

Here are the methods I use in 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;
}

And the ones in 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;
}

Here's an example in 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

And an example in 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

As you can see, when I do the opposite operation, the final Hex value is equal to the first one, which means the way I convert is potentially good in both languages individually. But I don't understand why the conversion from Hex to a byte array is different in both languages. I thought Hexadecimal was simply a number on another base.

Thanks for the help

Cydrick

Update

I fixed this issue by replacing the C# code with the following code:

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;
}

解决方案

But, when I convert the same Hex value to a Byte Array on both languages, the output is different.

All you're seeing is that bytes are signed in Java and unsigned in C#. So if you add 256 to any negative value in Java, you'll get the value shown in C#. The actual bits in the values are the same - it's just a matter of whether the top bit is treated as a sign bit or not.

EDIT: As noted in comments, if you're ever using the byte as an integer outside the debugger output, you can always use:

int someInt = someByte & 0xff;

to get the unsigned value.

这篇关于C#和Java中的十六进制到字节数组给出不同的结果的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆