39

I hope this isn't too much of a stupid question, I have looked on 5 different pages of Google results but haven't been able to find anything on this.

What I need to do is convert a string that contains all Hex characters into ASCII for example

String fileName = 

75546f7272656e745c436f6d706c657465645c6e667375635f6f73745f62795f6d757374616e675c50656e64756c756d2d392c303030204d696c65732e6d7033006d7033006d7033004472756d202620426173730050656e64756c756d00496e2053696c69636f00496e2053696c69636f2a3b2a0050656e64756c756d0050656e64756c756d496e2053696c69636f303038004472756d2026204261737350656e64756c756d496e2053696c69636f30303800392c303030204d696c6573203c4d757374616e673e50656e64756c756d496e2053696c69636f3030380050656e64756c756d50656e64756c756d496e2053696c69636f303038004d50330000

Every way I have seen makes it seems like you have to put it into an array first. Is there no way to loop through each two and convert them?

Brayden
  • 147
  • 1
  • 10
James
  • 423
  • 1
  • 5
  • 6

7 Answers7

103

Just use a for loop to go through each couple of characters in the string, convert them to a character and then whack the character on the end of a string builder:

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);

Or (Java 8+) if you're feeling particularly uncouth, use the infamous "fixed width string split" hack to enable you to do a one-liner with streams instead:

System.out.println(Arrays
        .stream(hex.split("(?<=\\G..)")) //https://stackoverflow.com/questions/2297347/splitting-a-string-at-every-n-th-character
        .map(s -> Character.toString((char)Integer.parseInt(s, 16)))
        .collect(Collectors.joining()));

Either way, this gives a few lines starting with the following:

uTorrent\Completed\nfsuc_ost_by_mustang\Pendulum-9,000 Miles.mp3

Hmmm... :-)

Michael Berry
  • 70,193
  • 21
  • 157
  • 216
  • 97
    This question wins the award of "Most Self-Incriminating Question of the Year". – Cory Klein Jan 24 '11 at 18:46
  • 4
    Ha ha good point, but lucky for me this file is from a once live case so I'm in the clear but I didn't think ha ha! Made me laugh though :) – James Jan 24 '11 at 18:54
  • 1
    Thank you "berry120" that has helped me loads! :) – James Jan 24 '11 at 18:56
  • Given that the size of the string is known in advance, one might optimise the `StringBuilder` to hold it all or even use just a `char[]`. Only relevant if this will be run often, of course. – entonio Feb 22 '13 at 16:16
  • 5
    I know this is an old question but just for info Guava 14 introduced a [BaseEncoding](http://docs.guava-libraries.googlecode.com/git/javadoc/com/google/common/io/BaseEncoding.html) class which would be used like `new String(BaseEncoding.base16().lowerCase().decode(hex), Charsets.US_ASCII)` - the BaseEncoding instance can be cached as it's immutable – Matt Mar 22 '13 at 11:27
12

Easiest way to do it with javax.xml.bind.DatatypeConverter:

    String hex = "75546f7272656e745c436f6d706c657465645c6e667375635f6f73745f62795f6d757374616e675c50656e64756c756d2d392c303030204d696c65732e6d7033006d7033006d7033004472756d202620426173730050656e64756c756d00496e2053696c69636f00496e2053696c69636f2a3b2a0050656e64756c756d0050656e64756c756d496e2053696c69636f303038004472756d2026204261737350656e64756c756d496e2053696c69636f30303800392c303030204d696c6573203c4d757374616e673e50656e64756c756d496e2053696c69636f3030380050656e64756c756d50656e64756c756d496e2053696c69636f303038004d50330000";
    byte[] s = DatatypeConverter.parseHexBinary(hex);
    System.out.println(new String(s));
Nikita Koksharov
  • 10,283
  • 1
  • 62
  • 71
  • 2
    This solution gives the same results as the accepted answer. – LeHill Sep 08 '16 at 20:34
  • in my case the string started with 0x and I got an exception that complained about illegal characters (the x in this case) so I just had to do a substring(2) to exclude those. ^_^ – Ted Delezene Sep 24 '18 at 22:44
  • I had different outputs, I dont know what went wrong. String : B54075546f7272656e745c436f6d706c657465645c6e667375635f6f73745f62795f6d757374616e675c50656e64756c75 with out DatatypeConverter : µ@uTorrent\Completed\nfsuc_ost_by_mustang\Pendulu with DatatypeConverter : �@uTorrent\Completed\nfsuc_ost_by_mustang\Pendulu – arjuncc Oct 14 '21 at 07:47
3
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));
}
Mike Samuel
  • 118,113
  • 30
  • 216
  • 245
2

Check out Convert a string representation of a hex dump to a byte array using Java?

Disregarding encoding, etc. you can do new String (hexStringToByteArray("75546..."));

Community
  • 1
  • 1
Andrew T Finnell
  • 13,417
  • 3
  • 33
  • 49
2

So as I understand it, you need to pull out successive pairs of hex digits, then decode that 2-digit hex number and take the corresponding char:

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();
Neil Coffey
  • 21,615
  • 7
  • 62
  • 83
1
//%%%%%%%%%%%%%%%%%%%%%% 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;
}
kleopatra
  • 51,061
  • 28
  • 99
  • 211
maryan
  • 21
  • 1
0

To this case, I have a hexadecimal data format into an int array and I want to convert them on 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]));
}