2015-04-16 90 views
0

我将字符串从UTF-8转换为CP1047,然后对其执行十六进制编码,这很好。接下来,我正在做的是转换回来,使用解码十六进制字符串并以UTF-8格式在控制台上显示它。问题是我没有得到正确的字符串,我传递给编码方法。下面是我编写了一段代码:字符串十六进制编码和解码

public class HexEncodeDecode { 

    public static void main(String[] args) throws UnsupportedEncodingException, 
      DecoderException { 
     String reqMsg = "ISO0150000150800C220000080000000040000050000000215102190000000014041615141800001427690161 0B0 00"; 
     char[] hexed = getHex(reqMsg, "UTF-8", "Cp1047"); 

     System.out.println(hexed); 

     System.out.println(getString(hexed)); 
    } 

    public static char[] getHex(String source, String inputCharacterCoding, 
      String outputCharacterCoding) throws UnsupportedEncodingException { 
     return Hex.encodeHex(new String(source.getBytes(inputCharacterCoding), 
       outputCharacterCoding).getBytes(), false); 
    } 

    public static String getString(char[] source) throws DecoderException, 
      UnsupportedEncodingException { 
     return new String(Hex.decodeHex(source), Charset.forName("UTF-8")); 
    } 
} 

输出我得到的是:

C3B1C3AB7CC290C291C295C290C290C290C290C291C295C290C298C290C290C3A41616C290C290C290C290C290C298C290C290C290C290C290C290C290C290C294C290C290C290C290C290C295C290C290C290C290C290C290C29016C291C295C291C29016C291C299C290C290C290C290C290C290C290C290C291C294C290C294C291C296C291C295C291C294C291C298C290C290C290C290C291C2941604C296C299C290C291C296C291C280C290C3A2C290C280C280C280C280C290C290C290C29116C293C294C295C290C290C294C29116C293C294 
ñë|äâ 

因此,需要在打印输入字符串返回帮助。

预计产出将是:

C3B1C3AB7CC290C291C295C290C290C290C290C291C295C290C298C290C290C3A41616C290C290C290C290C290C298C290C290C290C290C290C290C290C290C294C290C290C290C290C290C295C290C290C290C290C290C290C29016C291C295C291C29016C291C299C290C290C290C290C290C290C290C290C291C294C290C294C291C296C291C295C291C294C291C298C290C290C290C290C291C2941604C296C299C290C291C296C291C280C290C3A2C290C280C280C280C280C290C290C290C29116C293C294C295C290C290C294C29116C293C294 
ISO0150000150800C220000080000000040000050000000215102190000000014041615141800001427690161 0B0 00
+1

显示Hex.encodeHex的'代码。另外,您正在使用'.getBytes()'(第二个调用),而不使用字符集。 – fge

+0

Hex.encodeHex()来自apache commons编解码库 – Arpit

回答

3
new String(source.getBytes(inputCharacterCoding), outputCharacterCoding) 
    .getBytes() 

这可能不会做你认为它。

第一件事情第一件事:a String没有编码。在我之后重复:a String没有编码

A String只是一个旨在表示字符的令牌序列。恰恰为此,Java使用了一系列的char s。他们也可以成为信鸽。

UTF8,CP1047和其他只是字符编码;可以执行两个操作:

  • 编码:将载体鸽子流(chars)变成字节流;
  • 解码:将一串字节转变为载体鸽子流(char s)。

基本上,你的基本假设是错误的;您无法将编码与String关联。你真正的输入应该是一个byte流(通常不是一个字节数组),你知道是一个特定的编码(在你的情况下,UTF-8)的结果,你想用另一个字符集重新编码在你的情况下,CP1047)。

“秘密”在这里抛出一个真正的答案将是你的Hex.encodeHex()方法的代码,但你不显示它,所以这是一个很好的答案,我可以召集。

+0

https://commons.apache.org/proper/commons-codec/apidocs/org/apache/commons/codec/binary/Hex.html –

+0

@AlastairMcCormack ow .. 。方法本身的描述相当混乱:/ – fge

+0

相当 - 我同意,首先阅读并不容易理解:) –

1

速战速决(虽然有点丑)是改变getString()到:

public static String getString(char[] source) throws DecoderException, UnsupportedEncodingException { 
     return new String(new String(Hex.decodeHex(source), Charset.forName("UTF-8")).getBytes("Cp1047"),"UTF-8"); 
} 

由于FGE已经提到的,您切换字符和字节,这是不同双鞋之间转换。因此,在这个快速解决方案中,首先使用UTF-8获取您的十六进制解码,然后将其编码为一个Cp1047字节数组,最后使用UTF-8字符集将其解码为字符串。

正如我已经说过的,这只是一个快速的单线解决方法,而不是最干净的解决方案,因为错误已在十六进制编码期间完成。

1

reqMsg不再具有编码,因此如果尝试从UTF-8转换为“Cp1047”,它就毫无意义(并且有害)。

如果reqMsg未来将来自外部来源,例如来自磁盘或网络,那么您将不得不解码 - 可能这是混淆来自的地方。也许你会这样做:UTF-8-> Unicode(字符串) - > CP1047-> HEX。当你将它写入标准输出时,十六进制可能会被ASCII编码。

后续的范例会依据转换后您的原始字符串CP1047(Unicode的> CP1047-> HEX)的ASCII十六进制字符串:()`

String reqMsg = "ISO0150000150800C220000080000000040000050000000215102190000000014041615141800001427690161 0B0 00"; 

    // encode to cp1047 represented as Hex 
    byte[] reqMsqBytes = reqMsg.getBytes("Cp1047"); 
    char[] hex = Hex.encodeHex(reqMsqBytes); 
    System.out.println(hex); 

    // decode 
    String respMsqBytes = new String(Hex.decodeHex(hex), "Cp1047"); 
    System.out.println(respMsqBytes); 
相关问题