带有重音的Java String HEX到String ASCII

时间:2013-04-01 18:41:06

标签: java utf-8 hex ascii

我有字符串String hex = "6174656ec3a7c3a36f";,我想获得String output = "atenção"但是在我的测试中我只得到String output = "aten????o"; 我做错了什么?

String hex = "6174656ec3a7c3a36f";
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); //here is the output "aten????o"

4 个答案:

答案 0 :(得分:5)

考虑

String hex = "6174656ec3a7c3a36f";                                  // AAA
ByteBuffer buff = ByteBuffer.allocate(hex.length()/2);
for (int i = 0; i < hex.length(); i+=2) {
    buff.put((byte)Integer.parseInt(hex.substring(i, i+2), 16));
}
buff.rewind();
Charset cs = Charset.forName("UTF-8");                              // BBB
CharBuffer cb = cs.decode(buff);                                    // BBB
System.out.println(cb.toString());                                  // CCC

打印:atenção

基本上,您的十六进制字符串表示字节的十六进制编码,表示以UTF-8编码时字符串atenção中的字符

解码:

  • 首先必须从十六进制字符串转到字节(AAA)
  • 然后从字节转到字符(BBB) - 这取决于编码,在您的情况下是UTF-8。
  • 从字符转到字符串(CCC)

答案 1 :(得分:4)

您的十六进制字符串似乎表示UTF-8字符串,而不是ISO-8859-1。

我可以这样说的原因是,如果它是ISO-8859-1,那么每个角色你有两个十六进制数字。您的十六进制字符串有18个字符,但您的预期输出只有7个字符。因此,十六进制字符串必须是可变宽度编码,而不是像ISO-8859-1那样每个字符的单个字节。

以下程序生成输出:atenção

    String hex = "6174656ec3a7c3a36f";
    ByteArrayOutputStream baos = new ByteArrayOutputStream();
    for (int i = 0; i < hex.length(); i += 2) {
      String str = hex.substring(i, i + 2);
      int byteVal = Integer.parseInt(str, 16);
      baos.write(byteVal);
    } 
    String s = new String(baos.toByteArray(), Charset.forName("UTF-8"));

如果您将UTF-8更改为ISO-8859-1,则会看到:atenção

答案 2 :(得分:3)

Java Strings are Unicode:每个字符以16位编码。你的字符串是 - 我想 - 一个“C”字符串。您必须知道字符编码器的名称并使用CharsetDecoder

import java.nio.ByteBuffer;
import java.nio.CharBuffer;
import java.nio.charset.CharacterCodingException;
import java.nio.charset.Charset;
import java.nio.charset.CharsetDecoder;

public class Char8859_1Decoder {

   public static void main( String[] args ) throws CharacterCodingException {
      String hex = "6174656ec3a7c3a36f";
      int len = hex.length();
      byte[] cStr = new byte[len/2];
      for( int i = 0; i < len; i+=2 ) {
         cStr[i/2] = (byte)Integer.parseInt( hex.substring( i, i+2 ), 16 );
      }
      CharsetDecoder decoder = Charset.forName( "UTF-8" ).newDecoder();
      CharBuffer cb = decoder.decode( ByteBuffer.wrap( cStr ));
      System.out.println( cb.toString());
   }
}

答案 3 :(得分:2)

ç和ã是16位字符,所以它们不是你在解码例程中假设的字节,而是由一个完整的单词表示。

我不是将每个字节转换为char,而是将字节转换为java Bytes,然后使用字符串例程将Bytes数组解码为字符串,从而允许java执行确定解码例程的枯燥任务。 / p>

当然,java可能猜错了,所以你可能必须提前知道编码是什么,根据@Aubin或@Martin Ellis给出的答案