我正在寻找一种方法来转换一个长字符串(从转储),它表示十六进制值到字节数组。
我不可能比在这里发布同样问题的人表达得更好。
但是为了保持它的原创性,我将以自己的方式表达它:假设我有一个字符串“00A0BF”,我希望将其解释为
byte[] {0x00,0xA0,0xBf}
我该怎么办?
我是一个Java新手,最后使用BigInteger并注意前导十六进制零。但我认为它很丑,我肯定我错过了一些简单的东西。
我正在寻找一种方法来转换一个长字符串(从转储),它表示十六进制值到字节数组。
我不可能比在这里发布同样问题的人表达得更好。
但是为了保持它的原创性,我将以自己的方式表达它:假设我有一个字符串“00A0BF”,我希望将其解释为
byte[] {0x00,0xA0,0xBf}
我该怎么办?
我是一个Java新手,最后使用BigInteger并注意前导十六进制零。但我认为它很丑,我肯定我错过了一些简单的东西。
当前回答
如果您的需求不仅仅是偶尔的转换,那么您可以使用HexUtils。
例子:
byte[] byteArray = Hex.hexStrToBytes("00A0BF");
这是最简单的情况。您的输入可能包含分隔符(如MAC地址、证书指纹等),您的输入可能是流式的,等等。在这种情况下,引入像HexUtils这样的外部库(无论多么小)变得更容易。
在JDK 17中,HexFormat类将满足大多数需求,而对HexUtils这样的类的需求将大大减少。然而,HexUtils仍然可以用于一些事情,比如从十六进制(流)转换非常大的量或漂亮的十六进制打印(想想有线转储),这是JDK HexFormat类不能做的。
(完全披露:我是HexUtils的作者)
其他回答
迟到了,但我已经把DaveL上面的答案合并到一个具有反向操作的类中——以防它有所帮助。
public final class HexString {
private static final char[] digits = "0123456789ABCDEF".toCharArray();
private HexString() {}
public static final String fromBytes(final byte[] bytes) {
final StringBuilder buf = new StringBuilder();
for (int i = 0; i < bytes.length; i++) {
buf.append(HexString.digits[(bytes[i] >> 4) & 0x0f]);
buf.append(HexString.digits[bytes[i] & 0x0f]);
}
return buf.toString();
}
public static final byte[] toByteArray(final String hexString) {
if ((hexString.length() % 2) != 0) {
throw new IllegalArgumentException("Input string must contain an even number of characters");
}
final int len = hexString.length();
final byte[] data = new byte[len / 2];
for (int i = 0; i < len; i += 2) {
data[i / 2] = (byte) ((Character.digit(hexString.charAt(i), 16) << 4)
+ Character.digit(hexString.charAt(i + 1), 16));
}
return data;
}
}
和JUnit测试类:
public class TestHexString {
@Test
public void test() {
String[] tests = {"0FA1056D73", "", "00", "0123456789ABCDEF", "FFFFFFFF"};
for (int i = 0; i < tests.length; i++) {
String in = tests[i];
byte[] bytes = HexString.toByteArray(in);
String out = HexString.fromBytes(bytes);
System.out.println(in); //DEBUG
System.out.println(out); //DEBUG
Assert.assertEquals(in, out);
}
}
}
下面是一个实际有效的方法(基于之前几个半正确的答案):
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;
}
我能看到的唯一可能的问题是,如果输入字符串非常长;调用toCharArray()会复制字符串的内部数组。
编辑:哦,顺便说一下,字节在Java中是有符号的,所以您的输入字符串转换为[0,-96,-65]而不是[0,160,191]。但你可能已经知道了。
我喜欢这个角色。数位解,我是这样解的
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;
}
一行程序:
import javax.xml.bind.DatatypeConverter;
public static String toHexString(byte[] array) {
return DatatypeConverter.printHexBinary(array);
}
public static byte[] toByteArray(String s) {
return DatatypeConverter.parseHexBinary(s);
}
警告:
在Java 9 Jigsaw中,这不再是(默认)Java的一部分。se根 设置,否则将导致ClassNotFoundException,除非您指定 ——添加模块java.se.ee(感谢@eckes) Android上不支持(感谢Fabian注意到这一点),但如果您的系统由于某种原因缺少javax.xml,您可以只使用源代码。感谢@Bert Regelink提取源代码。
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;
}