我正在寻找一种方法来转换一个长字符串(从转储),它表示十六进制值到字节数组。
我不可能比在这里发布同样问题的人表达得更好。
但是为了保持它的原创性,我将以自己的方式表达它:假设我有一个字符串“00A0BF”,我希望将其解释为
byte[] {0x00,0xA0,0xBf}
我该怎么办?
我是一个Java新手,最后使用BigInteger并注意前导十六进制零。但我认为它很丑,我肯定我错过了一些简单的东西。
我正在寻找一种方法来转换一个长字符串(从转储),它表示十六进制值到字节数组。
我不可能比在这里发布同样问题的人表达得更好。
但是为了保持它的原创性,我将以自己的方式表达它:假设我有一个字符串“00A0BF”,我希望将其解释为
byte[] {0x00,0xA0,0xBf}
我该怎么办?
我是一个Java新手,最后使用BigInteger并注意前导十六进制零。但我认为它很丑,我肯定我错过了一些简单的东西。
当前回答
我的正式解决方案:
/**
* Decodes a hexadecimally encoded binary string.
* <p>
* Note that this function does <em>NOT</em> convert a hexadecimal number to a
* binary number.
*
* @param hex Hexadecimal representation of data.
* @return The byte[] representation of the given data.
* @throws NumberFormatException If the hexadecimal input string is of odd
* length or invalid hexadecimal string.
*/
public static byte[] hex2bin(String hex) throws NumberFormatException {
if (hex.length() % 2 > 0) {
throw new NumberFormatException("Hexadecimal input string must have an even length.");
}
byte[] r = new byte[hex.length() / 2];
for (int i = hex.length(); i > 0;) {
r[i / 2 - 1] = (byte) (digit(hex.charAt(--i)) | (digit(hex.charAt(--i)) << 4));
}
return r;
}
private static int digit(char ch) {
int r = Character.digit(ch, 16);
if (r < 0) {
throw new NumberFormatException("Invalid hexadecimal string: " + ch);
}
return r;
}
类似于PHP的hex2bin()函数,但采用Java风格。
例子:
String data = new String(hex2bin("6578616d706c65206865782064617461"));
// data value: "example hex data"
其他回答
Bert Regelink提出的准则根本不起作用。 试试下面的方法:
import javax.xml.bind.DatatypeConverter;
import java.io.*;
public class Test
{
@Test
public void testObjectStreams( ) throws IOException, ClassNotFoundException
{
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
String stringTest = "TEST";
oos.writeObject( stringTest );
oos.close();
baos.close();
byte[] bytes = baos.toByteArray();
String hexString = DatatypeConverter.printHexBinary( bytes);
byte[] reconvertedBytes = DatatypeConverter.parseHexBinary(hexString);
assertArrayEquals( bytes, reconvertedBytes );
ByteArrayInputStream bais = new ByteArrayInputStream(reconvertedBytes);
ObjectInputStream ois = new ObjectInputStream(bais);
String readString = (String) ois.readObject();
assertEquals( stringTest, readString);
}
}
这里有另一个版本,它支持奇数长度的字符串,而不诉诸字符串连接。
public static byte[] hexStringToByteArray(String input) {
int len = input.length();
if (len == 0) {
return new byte[] {};
}
byte[] data;
int startIdx;
if (len % 2 != 0) {
data = new byte[(len / 2) + 1];
data[0] = (byte) Character.digit(input.charAt(0), 16);
startIdx = 1;
} else {
data = new byte[len / 2];
startIdx = 0;
}
for (int i = startIdx; i < len; i += 2) {
data[(i + 1) / 2] = (byte) ((Character.digit(input.charAt(i), 16) << 4)
+ Character.digit(input.charAt(i+1), 16));
}
return data;
}
我知道这是一个非常老的帖子,但仍然喜欢添加我的便士价值。
如果我真的需要编码一个简单的十六进制字符串到二进制转换器,我想这样做。
public static byte[] hexToBinary(String s){
/*
* skipped any input validation code
*/
byte[] data = new byte[s.length()/2];
for( int i=0, j=0;
i<s.length() && j<data.length;
i+=2, j++)
{
data[j] = (byte)Integer.parseInt(s.substring(i, i+2), 16);
}
return data;
}
我喜欢这个角色。数位解,我是这样解的
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;
}
下面是一个实际有效的方法(基于之前几个半正确的答案):
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]。但你可能已经知道了。