使用 Java 将十六进制转储的字符串表示形式转换为字节数组?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/140131/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-11 08:48:14  来源:igfitidea点击:

Convert a string representation of a hex dump to a byte array using Java?

javabytehexdump

提问by rafraf

I am looking for a way to convert a long string (from a dump), that represents hex values into a byte array.

我正在寻找一种将表示十六进制值的长字符串(从转储)转换为字节数组的方法。

I couldn't have phrased it better than the person that posted the same question here.

我不能比在这里发布相同问题的人更好地表达它

But to keep it original, I'll phrase it my own way: suppose I have a string "00A0BF"that I would like interpreted as the

但为了保持原始,我会用我自己的方式来表达它:假设我有一个字符串"00A0BF",我想将它解释为

byte[] {0x00,0xA0,0xBf}

what should I do?

我该怎么办?

I am a Java novice and ended up using BigIntegerand watching out for leading hex zeros. But I think it is ugly and I am sure I am missing something simple.

我是一名 Java 新手,最终使用BigInteger并注意前导十六进制零。但我认为它很丑,我确信我错过了一些简单的东西。

采纳答案by Dave L.

Here's a solution that I think is better than any posted so far:

这是我认为比迄今为止发布的任何解决方案都更好的解决方案:

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

Reasons why it is an improvement:

改进的原因:

  • Safe with leading zeros (unlike BigInteger) and with negative byte values (unlike Byte.parseByte)

  • Doesn't convert the String into a char[], or create StringBuilder and String objects for every single byte.

  • No library dependencies that may not be available

  • 安全的前导零(与 BigInteger 不同)和负字节值(与 Byte.parseByte 不同)

  • 不会将 String 转换为char[],也不会为每个字节创建 StringBuilder 和 String 对象。

  • 没有可能不可用的库依赖项

Feel free to add argument checking via assertor exceptions if the argument is not known to be safe.

assert如果不知道参数是否安全,请随意添加参数检查 via或 exceptions。

回答by skaffman

The Hex class in commons-codec should do that for you.

commons-codec 中的 Hex 类应该为您做到这一点。

http://commons.apache.org/codec/

http://commons.apache.org/codec/

import org.apache.commons.codec.binary.Hex;
...
byte[] decoded = Hex.decodeHex("00A0BF");
// 0x00 0xA0 0xBF

回答by pfranza

I've always used a method like

我一直使用这样的方法

public static final byte[] fromHexString(final String s) {
    String[] v = s.split(" ");
    byte[] arr = new byte[v.length];
    int i = 0;
    for(String val: v) {
        arr[i++] =  Integer.decode("0x" + val).byteValue();

    }
    return arr;
}

this method splits on space delimited hex values but it wouldn't be hard to make it split the string on any other criteria such as into groupings of two characters.

此方法在空格分隔的十六进制值上拆分,但不难将字符串拆分为任何其他标准,例如分成两个字符的分组。

回答by Bob King

I think will do it for you. I cobbled it together from a similar function that returned the data as a string:

我想会为你做的。我用一个类似的函数将它拼凑在一起,该函数将数据作为字符串返回:

private static byte[] decode(String encoded) {
    byte result[] = new byte[encoded/2];
    char enc[] = encoded.toUpperCase().toCharArray();
    StringBuffer curr;
    for (int i = 0; i < enc.length; i += 2) {
        curr = new StringBuffer("");
        curr.append(String.valueOf(enc[i]));
        curr.append(String.valueOf(enc[i + 1]));
        result[i] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

回答by Blair Conrad

EDIT: as pointed out by @mmyers, this method doesn't work on input that contains substrings corresponding to bytes with the high bit set ("80" - "FF"). The explanation is at Bug ID: 6259307 Byte.parseByte not working as advertised in the SDK Documentation.

编辑:正如@mmyers 所指出的,此方法不适用于包含与高位集(“80”-“FF”)的字节对应的子字符串的输入。解释在Bug ID: 6259307 Byte.parseByte not working as adin the SDK Documentation 中

public static final byte[] fromHexString(final String s) {
    byte[] arr = new byte[s.length()/2];
    for ( int start = 0; start < s.length(); start += 2 )
    {
        String thisByte = s.substring(start, start+2);
        arr[start/2] = Byte.parseByte(thisByte, 16);
    }
    return arr;
}

回答by Michael Myers

Here is a method that actually works (based on several previous semi-correct answers):

这是一种实际有效的方法(基于之前的几个半正确答案):

private static byte[] fromHexString(final String encoded) {
    if ((encoded.length() % 2) != 0)
        throw new IllegalArgumentException("Input string must contain an even number of characters");

    final byte result[] = new byte[encoded.length()/2];
    final char enc[] = encoded.toCharArray();
    for (int i = 0; i < enc.length; i += 2) {
        StringBuilder curr = new StringBuilder(2);
        curr.append(enc[i]).append(enc[i + 1]);
        result[i/2] = (byte) Integer.parseInt(curr.toString(), 16);
    }
    return result;
}

The only possible issue that I can see is if the input string is extremely long; calling toCharArray() makes a copy of the string's internal array.

我能看到的唯一可能的问题是输入字符串是否非常长;调用 toCharArray() 会复制字符串的内部数组。

EDIT: Oh, and by the way, bytes are signed in Java, so your input string converts to [0, -96, -65] instead of [0, 160, 191]. But you probably knew that already.

编辑:哦,顺便说一下,字节是用 Java 签名的,所以你的输入字符串转换为 [0, -96, -65] 而不是 [0, 160, 191]。但你可能已经知道了。

回答by Dave L.

Actually, I think the BigInteger is solution is very nice:

实际上,我认为 BigInteger is 解决方案非常好:

new BigInteger("00A0BF", 16).toByteArray();

Edit: Not safe for leading zeros, as noted by the poster.

编辑:如海报所述,前导零不安全

回答by Sniper

The BigInteger()Method from java.math is very Slow and not recommandable.

BigInteger()java.math 中的方法非常慢且不可推荐。

Integer.parseInt(HEXString, 16)

Integer.parseInt(HEXString, 16)

can cause problems with some characters without converting to Digit / Integer

可能会导致某些字符出现问题而不转换为数字/整数

a Well Working method:

一个好的工作方法:

Integer.decode("0xXX") .byteValue()

Function:

功能:

public static byte[] HexStringToByteArray(String s) {
    byte data[] = new byte[s.length()/2];
    for(int i=0;i < s.length();i+=2) {
        data[i/2] = (Integer.decode("0x"+s.charAt(i)+s.charAt(i+1))).byteValue();
    }
    return data;
}

Have Fun, Good Luck

玩得开心,祝你好运

回答by David V

public static byte[] hex2ba(String sHex) throws Hex2baException {
    if (1==sHex.length()%2) {
        throw(new Hex2baException("Hex string need even number of chars"));
    }

    byte[] ba = new byte[sHex.length()/2];
    for (int i=0;i<sHex.length()/2;i++) {
        ba[i] = (Integer.decode(
                "0x"+sHex.substring(i*2, (i+1)*2))).byteValue();
    }
    return ba;
}

回答by Kernel Panic

I like the Character.digit solution, but here is how I solved it

我喜欢 Character.digit 解决方案,但这是我的解决方法

public byte[] hex2ByteArray( String hexString ) {
    String hexVal = "0123456789ABCDEF";
    byte[] out = new byte[hexString.length() / 2];

    int n = hexString.length();

    for( int i = 0; i < n; i += 2 ) {
        //make a bit representation in an int of the hex value 
        int hn = hexVal.indexOf( hexString.charAt( i ) );
        int ln = hexVal.indexOf( hexString.charAt( i + 1 ) );

        //now just shift the high order nibble and add them together
        out[i/2] = (byte)( ( hn << 4 ) | ln );
    }

    return out;
}