【问题标题】:Convert a String of Hex into ASCII in Java在Java中将十六进制字符串转换为ASCII
【发布时间】:2011-06-14 17:07:23
【问题描述】:

我希望这不是一个愚蠢的问题,我查看了 5 个不同页面的 Google 结果,但没有找到任何相关内容。

我需要做的是将包含所有十六进制字符的字符串转换为 ASCII,例如

String fileName = 

75546f7272656e745c436f6d706c657465645c6e667375635f6f73745f62795f6d757374616e675c50656e64756c756d2d392c303030204d696c65732e6d7033006d7033006d7033004472756d202620426173730050656e64756c756d00496e2053696c69636f00496e2053696c69636f2a3b2a0050656e64756c756d0050656e64756c756d496e2053696c69636f303038004472756d2026204261737350656e64756c756d496e2053696c69636f30303800392c303030204d696c6573203c4d757374616e673e50656e64756c756d496e2053696c69636f3030380050656e64756c756d50656e64756c756d496e2053696c69636f303038004d50330000

我所看到的每一种方式都让人觉得你必须先将它放入一个数组中。有没有办法循环遍历每两个并转换它们?

【问题讨论】:

    标签: java string ascii hex


    【解决方案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://stackoverflow.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]));
            }
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 2014-11-16
              • 2011-11-21
              • 2015-05-22
              • 2011-10-26
              • 1970-01-01
              • 2015-04-30
              相关资源
              最近更新 更多