C# 十六进制字串 转 Byte数组

字符串转字节阵列:Hex到ByteArray转换
  1. ///<summary>Convert a string of hex digits (ex: E4 CA B2) to a byte array. </summary>  
  2. ///<param name="s">The string containing the hex digits (with or without spaces).</param>  
  3. ///<returns>Returns an array of bytes.</returns>  
  4. private byte[] HexStringToByteArray(string s)  
  5. {  
  6.     s = s.Replace("   "" ");  
  7.     byte[] buffer = new byte[s.Length / 2];  
  8.     for (int i = 0; i < s.Length; i += 2)  
  9.        buffer[i / 2] = (byte)Convert.ToByte(s.Substring(i, 2), 16);  
  10.        return buffer;  
  11. }  


来源:http://blog.youkuaiyun.com/neverup_/article/details/5968825


<think>我们之前讨论的是十六进制字符串换为byte数组的Java实现方法。用户给出了一个具体的例子:"AA550305010005C8"。 在Java中,我们可以通过多种方式实现这个换。常见的方法包括: 1. 使用`BigInteger`类(适用于大字符串,但可能不是最高效的方式) 2. 逐个字符解析,每两个字符组合一个字节(因为一个字节由两个十六进制字符表示) 3. 使用Java标准库中的工具类,如`javax.xml.bind.DatatypeConverter`(但在较新的Java版本中可能已被移除) 4. 从Java 17开始,可以使用`java.util.HexFormat`(推荐方式,但需要较新的Java版本) 考虑到兼容性,我们这里展示第二种方法,因为它适用于所有Java版本,且效率较高。 步骤如下: - 检查字符串长度是否为偶数(因为每个字节由两个十六进制字符表示) - 创建一个byte数组,长度为字符串长度的一半 - 遍历字符串,每次取两个字符,将它们换为一个byte值 - 使用`Integer.parseInt(hexString, 16)`将两个字符组的子字符串换为整数,然后换为byte 注意:由于`Integer.parseInt`返回的是int,而int可能是32位,我们需要将其强制换为byte(8位)。因为byte是有符号的,所以当换的数值大于127时,会变负数,这是正常的,因为byte在Java中是有符号类型。 例如,十六进制字符串"AA"换为整数是170,而170在byte中表示负数(因为byte范围是-128到127),这是正确的。因为170超过了127,所以它会被解释为-86(因为170的二进制是10101010,作为有符号byte的最高位是1,所以是负数)。但是,当我们使用这个byte数组时,我们通常关心的是它的二进制表示,而不是它的十进制值。 如果我们希望避免负数,我们应该使用无符号类型来处理,但在byte数组中存储时,它仍然会以补码形式表示。 实现代码: ```java public static byte[] hexStringToByteArray(String s) { int len = s.length(); if (len % 2 != 0) { throw new IllegalArgumentException("Hex string must have even number of characters."); } byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { // 每两个字符组一个十六进制数 String hex = s.substring(i, i + 2); // 将十六进制字符串解析为整数(基数16),然后byte data[i / 2] = (byte) Integer.parseInt(hex, 16); } return data; } ``` 另外,也可以使用字符数组和位运算来避免子字符串的创建,以提高效率(特别是在处理大字符串时): ```java public static byte[] hexStringToByteArray(String s) { int len = s.length(); if (len % 2 != 0) { throw new IllegalArgumentException("Hex string must have even number of characters."); } byte[] data = new byte[len / 2]; for (int i = 0; i < len; i += 2) { // 将字符换为数字 int high = Character.digit(s.charAt(i), 16); int low = Character.digit(s.charAt(i+1), 16); if (high == -1 || low == -1) { throw new IllegalArgumentException("Illegal hex character at position " + i); } data[i/2] = (byte) ( (high << 4) + low ); } return data; } ``` 第二种方法避免了创建子字符串,并且直接通过位运算组合两个十六进制数字,效率更高。 对于用户给出的例子:"AA550305010005C8",换后的byte数组应该是: [-86, 85, 3, 5, 1, 0, 5, -56] (使用第一种方法得到的十进制表示) 但是,如果我们以无符号的方式看待这些字节,那么每个字节对应的无符号值应该是: 0xAA (170), 0x55 (85), 0x03 (3), 0x05 (5), 0x01 (1), 0x00 (0), 0x05 (5), 0xC8 (200) 因此,这个换是正确的。 如果用户使用的是Java 17及以上版本,推荐使用`HexFormat`类: ```java HexFormat hexFormat = HexFormat.of(); byte[] bytes = hexFormat.parseHex(s); ``` 这种方法更简洁,且经过良好测试。 根据用户的需求,我们提供第二种方法的实现(避免子字符串)作为主要答案。 注意:如果字符串中包含空格或其他分隔符,需要先去除(比如使用`replaceAll("\\s", "")`),但用户给出的例子中没有空格。 现在,我们按照用户要求生相关问题。 </think>### Java实现十六进制字符串byte数组 在Java中,将十六进制字符串(如`AA550305010005C8`)换为`byte[]`数组的常见实现方法如下: #### 方法1:基础循环解析(推荐) ```java public static byte[] hexStringToByteArray(String hex) { int len = hex.length(); if (len % 2 != 0) { throw new IllegalArgumentException("十六进制字符串长度必须为偶数"); } byte[] bytes = new byte[len / 2]; for (int i = 0; i < len; i += 2) { // 每两个字符解析为一个字节 int byteValue = Integer.parseInt(hex.substring(i, i + 2), 16); bytes[i / 2] = (byte) byteValue; } return bytes; } ``` #### 方法2:使用位运算(更高性能) ```java public static byte[] hexStringToByteArray(String hex) { int len = hex.length(); byte[] bytes = new byte[len / 2]; for (int i = 0; i < len; i += 2) { // 直接换字符为数字值 int highNibble = Character.digit(hex.charAt(i), 16); int lowNibble = Character.digit(hex.charAt(i + 1), 16); // 合并高低4位 bytes[i / 2] = (byte) ((highNibble << 4) | lowNibble); } return bytes; } ``` #### 使用示例 ```java public static void main(String[] args) { String hexStr = "AA550305010005C8"; byte[] byteArray = hexStringToByteArray(hexStr); // 输出验证 for (byte b : byteArray) { System.out.printf("%02X ", b); // 输出: AA 55 03 05 01 00 05 C8 } } ``` ### 关键说明: 1. **字符处理**:每两个十六进制字符对应一个字节(8位) 2. **异常处理**: - 输入长度必须是偶数(每个字节由两个字符组) - 非法字符(非0-9/A-F/a-f)会抛出`NumberFormatException` 3. **换原理**: - 十六进制`AA` → 二进制`10101010` → 十进制`-86`(Java的byte为有符号类型) - 实际存储的二进制值与目标一致,负值属于正常现象 > 对于Java 17+用户,可直接使用标准库: > ```java > import java.util.HexFormat; > byte[] bytes = HexFormat.of().parseHex("AA550305010005C8"); > ``` ### 注意事项: - 如字符串含前缀`0x`需提前去除 - 大小写不敏感(`A`和`a`等效) - 输出负值属于正常现象(因Java的byte类型是有符号的)
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值