字符串十六进制编码和解码

时间:2015-04-16 12:59:53

标签: java string utf-8 ascii ebcdic

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

public class HexEncodeDecode {

    public static void main(String[] args) throws UnsupportedEncodingException,
            DecoderException {
        String reqMsg = "ISO0150000150800C220000080000000040000050000000215102190000000014041615141800001427690161 0B0    000123450041234";
        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    000123450041234

3 个答案:

答案 0 :(得分:5)

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

这可能不符合您的想法。

首先要做的事情是: String没有编码。在我之后重复: String没有编码

String只是一系列旨在表示字符的标记。只是为了这个目的,Java使用了char s的序列。它们也可以成为载体鸽。

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

  • 编码:将载体流(char s)转换为字节流;
  • 解码:将一个字节流转换为载体鸽子流(char s)。

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

这里的“秘密”是一个真正的答案,就是你的Hex.encodeHex()方法的代码,但是你没有显示它,所以这是我能回答的好答案。

答案 1 :(得分: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字符集将其解码回String。

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

答案 2 :(得分:1)

reqMsg不再有编码,因此尝试将其从UTF-8转换为" Cp1047"

是毫无意义的(并且具有破坏性)

如果reqMsg将来会来自外部来源,例如来自磁盘或网络,那么您将不得不进行解码 - 也许这就是混乱的来源。也许您正在做:UTF-8-> Unicode(字符串) - > CP1047-> HEX。当你把它写到stdout时,HEX很可能是ASCII编码的。

以下示例在转换为CP1047(Unicode-> CP1047-> HEX)后,根据原始字符串创建ASCII十六进制字符串:

    String reqMsg = "ISO0150000150800C220000080000000040000050000000215102190000000014041615141800001427690161 0B0    000123450041234";

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