在Java中将十六进制字符串转换为ASCII
Posted
技术标签:
【中文标题】在Java中将十六进制字符串转换为ASCII【英文标题】:Convert a String of Hex into ASCII in Java 【发布时间】:2011-06-14 17:07:23 【问题描述】:我希望这不是一个愚蠢的问题,我查看了 5 个不同页面的 Google 结果,但没有找到任何相关内容。
我需要做的是将包含所有十六进制字符的字符串转换为 ASCII,例如
String fileName =
75546f7272656e745c436f6d706c657465645c6e667375635f6f73745f62795f6d757374616e675c50656e64756c756d2d392c303030204d696c65732e6d7033006d7033006d7033004472756d202620426173730050656e64756c756d00496e2053696c69636f00496e2053696c69636f2a3b2a0050656e64756c756d0050656e64756c756d496e2053696c69636f303038004472756d2026204261737350656e64756c756d496e2053696c69636f30303800392c303030204d696c6573203c4d757374616e673e50656e64756c756d496e2053696c69636f3030380050656e64756c756d50656e64756c756d496e2053696c69636f303038004d50330000
我所看到的每一种方式都让人觉得你必须先将它放入一个数组中。有没有办法循环遍历每两个并转换它们?
【问题讨论】:
【参考方案1】:查看Convert a string representation of a hex dump to a byte array using Java?
不管编码等你都可以new String (hexStringToByteArray("75546..."));
【讨论】:
【参考方案2】:只需使用 for 循环遍历字符串中的每一对字符,将它们转换为一个字符,然后在字符串生成器的末尾敲击该字符:
String hex = "75546f7272656e745c436f6d706c657465645c6e667375635f6f73745f62795f6d757374616e675c50656e64756c756d2d392c303030204d696c65732e6d7033006d7033006d7033004472756d202620426173730050656e64756c756d00496e2053696c69636f00496e2053696c69636f2a3b2a0050656e64756c756d0050656e64756c756d496e2053696c69636f303038004472756d2026204261737350656e64756c756d496e2053696c69636f30303800392c303030204d696c6573203c4d757374616e673e50656e64756c756d496e2053696c69636f3030380050656e64756c756d50656e64756c756d496e2053696c69636f303038004d50330000";
StringBuilder output = new StringBuilder();
for (int i = 0; i < hex.length(); i+=2)
String str = hex.substring(i, i+2);
output.append((char)Integer.parseInt(str, 16));
System.out.println(output);
或者(Java 8+),如果你觉得特别笨拙,可以使用臭名昭著的“固定宽度字符串拆分”技巧,让你可以用流做单线:
System.out.println(Arrays
.stream(hex.split("(?<=\\G..)")) //https://***.com/questions/2297347/splitting-a-string-at-every-n-th-character
.map(s -> Character.toString((char)Integer.parseInt(s, 16)))
.collect(Collectors.joining()));
无论哪种方式,这都会给出以以下开头的几行:
uTorrent\Completed\nfsuc_ost_by_mustang\Pendulum-9,000 Miles.mp3
嗯... :-)
【讨论】:
本题获得“年度最自证其罪”奖。 哈哈好点,但幸运的是,这个文件来自一个曾经活过的案例,所以我很清楚,但我没想到哈哈!不过让我笑了:) 感谢帮助我加载的“berry120”! :) 鉴于字符串的大小是预先知道的,人们可能会优化StringBuilder
来保存它,甚至只使用char[]
。当然,只有在经常运行时才有意义。
我知道这是一个老问题,但仅供参考 Guava 14 引入了一个 BaseEncoding 类,可以像 new String(BaseEncoding.base16().lowerCase().decode(hex), Charsets.US_ASCII)
一样使用 - BaseEncoding 实例可以缓存,因为它是不可变的【参考方案3】:
据我了解,您需要提取连续的十六进制数字对,然后解码该 2 位十六进制数字并获取相应的字符:
String s = "...";
StringBuilder sb = new StringBuilder(s.length() / 2);
for (int i = 0; i < s.length(); i+=2)
String hex = "" + s.charAt(i) + s.charAt(i+1);
int ival = Integer.parseInt(hex, 16);
sb.append((char) ival);
String string = sb.toString();
【讨论】:
【参考方案4】:String hexToAscii(String s)
int n = s.length();
StringBuilder sb = new StringBuilder(n / 2);
for (int i = 0; i < n; i += 2)
char a = s.charAt(i);
char b = s.charAt(i + 1);
sb.append((char) ((hexToInt(a) << 4) | hexToInt(b)));
return sb.toString();
private static int hexToInt(char ch)
if ('a' <= ch && ch <= 'f') return ch - 'a' + 10;
if ('A' <= ch && ch <= 'F') return ch - 'A' + 10;
if ('0' <= ch && ch <= '9') return ch - '0';
throw new IllegalArgumentException(String.valueOf(ch));
【讨论】:
【参考方案5】://%%%%%%%%%%%%%%%%%%%%%% HEX to ASCII %%%%%%%%%%%%%%%%%%%%%%
public String convertHexToString(String hex)
String ascii="";
String str;
// Convert hex string to "even" length
int rmd,length;
length=hex.length();
rmd =length % 2;
if(rmd==1)
hex = "0"+hex;
// split into two characters
for( int i=0; i<hex.length()-1; i+=2 )
//split the hex into pairs
String pair = hex.substring(i, (i + 2));
//convert hex to decimal
int dec = Integer.parseInt(pair, 16);
str=CheckCode(dec);
ascii=ascii+" "+str;
return ascii;
public String CheckCode(int dec)
String str;
//convert the decimal to character
str = Character.toString((char) dec);
if(dec<32 || dec>126 && dec<161)
str="n/a";
return str;
【讨论】:
【参考方案6】:使用javax.xml.bind.DatatypeConverter
的最简单方法:
String hex = "75546f7272656e745c436f6d706c657465645c6e667375635f6f73745f62795f6d757374616e675c50656e64756c756d2d392c303030204d696c65732e6d7033006d7033006d7033004472756d202620426173730050656e64756c756d00496e2053696c69636f00496e2053696c69636f2a3b2a0050656e64756c756d0050656e64756c756d496e2053696c69636f303038004472756d2026204261737350656e64756c756d496e2053696c69636f30303800392c303030204d696c6573203c4d757374616e673e50656e64756c756d496e2053696c69636f3030380050656e64756c756d50656e64756c756d496e2053696c69636f303038004d50330000";
byte[] s = DatatypeConverter.parseHexBinary(hex);
System.out.println(new String(s));
【讨论】:
此解决方案给出的结果与接受的答案相同。 在我的例子中,字符串以 0x 开头,我得到一个异常,抱怨非法字符(在这种情况下是 x),所以我只需要做一个 substring(2) 来排除这些。 ^_^ 我有不同的输出,我不知道出了什么问题。字符串:B54075546f7272656e745c436f6d706c657465645c6e667375635f6f73745f62795f6d757374616e675c50656e64756c75与出DatatypeConverter:μ@ uTorrent的\完成\ nfsuc_ost_by_mustang \ Pendulu与DatatypeConverter:@uTorrent \完成\ nfsuc_ost_by_mustang \ Pendulu 跨度> 【参考方案7】:对于这种情况,我将十六进制数据格式转换为 int 数组,我想将它们转换为 String。
int[] encodeHex = new int[] 0x48, 0x65, 0x6c, 0x6c, 0x6f ; // Hello encode
for (int i = 0; i < encodeHex.length; i++)
System.out.print((char) (encodeHex[i]));
【讨论】:
以上是关于在Java中将十六进制字符串转换为ASCII的主要内容,如果未能解决你的问题,请参考以下文章
在 C 中将 ascii char[] 转换为十六进制 char[]
如何在 Python 中将单个字符转换为其十六进制 ASCII 值?