[英]Is this the best way to convert String hex to bytes?
Is this the best way to convert String hex to bytes?这是将十六进制字符串转换为字节的最佳方法吗? Or can you think a shorter/simpler?
或者你能想到一个更短/更简单的吗?
public static byte[] hexToBytes(String hex) {
return hexToBytes(hex.toCharArray());
}
public static byte[] hexToBytes(char[] hex) {
int length = hex.length / 2;
byte[] raw = new byte[length];
for (int i = 0; i < length; i++) {
int high = Character.digit(hex[i * 2], 16);
int low = Character.digit(hex[i * 2 + 1], 16);
int value = (high << 4) | low;
if (value > 127)
value -= 256;
raw[i] = (byte) value;
}
return raw;
}
byte[] yourBytes = new BigInteger(hexString, 16).toByteArray();
You don't need the subtraction of 256 when the value is greater than 127. Just cast the value to a byte.当值大于 127 时,您不需要减去 256。只需将值转换为一个字节。 For example,
byte b = (byte) 255
assigns a value of -1 to b
.例如,
byte b = (byte) 255
将值 -1 分配给b
。
A narrowing conversion on integer types simply discards the high-order bits that don't fit in the target type.整数类型的缩小转换只是丢弃不适合目标类型的高位。
private static byte[] hexToBytes(char[] hex)
{
byte[] raw = new byte[hex.length / 2];
for (int src = 0, dst = 0; dst < raw.length; ++dst) {
int hi = Character.digit(hex[src++], 16);
int lo = Character.digit(hex[src++], 16);
if ((hi < 0) || (lo < 0))
throw new IllegalArgumentException();
raw[dst] = (byte) (hi << 4 | lo);
}
return raw;
}
Unfortunately, using BigInteger
fails when there are leading zero bytes.不幸的是,当有前导零字节时,使用
BigInteger
失败。
I think your original approach is a good start.我认为你最初的方法是一个好的开始。 I made some tweaks:
我做了一些调整:
@NotNull
public static byte[] hexToBytes(@NotNull String hex)
{
return hexToBytes(hex.toCharArray());
}
@NotNull
public static byte[] hexToBytes(@NotNull char[] hex)
{
if (hex.length % 2 != 0)
throw new IllegalArgumentException("Must pass an even number of characters.");
int length = hex.length >> 1;
byte[] raw = new byte[length];
for (int o = 0, i = 0; o < length; o++) {
raw[o] = (byte) ((getHexCharValue(hex[i++]) << 4)
| getHexCharValue(hex[i++]));
}
return raw;
}
public static byte getHexCharValue(char c)
{
if (c >= '0' && c <= '9')
return (byte) (c - '0');
if (c >= 'A' && c <= 'F')
return (byte) (10 + c - 'A');
if (c >= 'a' && c <= 'f')
return (byte) (10 + c - 'a');
throw new IllegalArgumentException("Invalid hex character");
}
Note that Character.digit
is only available in Java 7, and it doesn't validate that the provided character is within the expected range.请注意,
Character.digit
仅在 Java 7 中可用,它不会验证提供的字符是否在预期范围内。 I like to throw exceptions when input data doesn't match my expectations, so I've added that.当输入数据不符合我的期望时,我喜欢抛出异常,所以我添加了它。
Here are some basic unit tests:下面是一些基本的单元测试:
@Test
public void hexToBytes()
{
assertArrayEquals(new byte[]{0x00, 0x01, 0x02}, Convert.hexToBytes("000102"));
assertArrayEquals(new byte[]{(byte) 0xFF, (byte) 0xFE, (byte) 0xFD}, Convert.hexToBytes("FFFEFD"));
assertArrayEquals(new byte[]{(byte) 0xFF}, Convert.hexToBytes("FF"));
assertArrayEquals(new byte[]{(byte) 0x00}, Convert.hexToBytes("00"));
assertArrayEquals(new byte[]{(byte) 0x01}, Convert.hexToBytes("01"));
assertArrayEquals(new byte[]{(byte) 0x7F}, Convert.hexToBytes("7F"));
assertArrayEquals(new byte[]{(byte) 0x80}, Convert.hexToBytes("80"));
}
@Test(expected = IllegalArgumentException.class)
public void hexToBytesThrowsIfOddNumberOfCharacters()
{
Convert.hexToBytes("12345"); // Odd number of characters
}
@Test(expected = IllegalArgumentException.class)
public void hexToBytesThrowsIfInvalidCharacters()
{
Convert.hexToBytes("ABCDEFGH"); // G and H are invalid in base 16
}
@Test
public void getHexCharValue()
{
assertEquals(0x0, Convert.getHexCharValue('0'));
assertEquals(0x1, Convert.getHexCharValue('1'));
assertEquals(0x9, Convert.getHexCharValue('9'));
assertEquals(0xa, Convert.getHexCharValue('A'));
assertEquals(0xf, Convert.getHexCharValue('F'));
assertEquals(0xa, Convert.getHexCharValue('a'));
assertEquals(0xf, Convert.getHexCharValue('f'));
}
@Test(expected = IllegalArgumentException.class)
public void getHexCharValueThrowsIfInvalid1()
{
Convert.getHexCharValue('z');
}
The easiest way:最简单的方法:
private static byte[] hexToBytes(char[] hex)
{
return DatatypeConverter.parseHexBinary(hex.toString());
}
You can use the Bouncy Castle Crypto package - Java & C# implementation of cryptographic algorithms.您可以使用Bouncy Castle Crypto包 - 加密算法的 Java 和 C# 实现。
// import org.bouncycastle.util.encoders.Hex;
String msgHex = Hex.toHexString("Ehlo-HEX!".getBytes());
byte[] msgBytes = Hex.decode(msgHex);
System.out.println("hex(" + new String(msgBytes) + ")=" + msgHex);
<dependency>
<groupId>org.bouncycastle</groupId>
<artifactId>bcprov-jdk15on</artifactId>
<version>1.65</version>
</dependency>
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.