Java中的Unicode Base64编码

4

我正在尝试将UTF8字符串编码和解码为base64。

理论上不是问题,但是在解码时似乎无法输出正确的字符,而是输出了问号(?)。


        String original = "خهعسيبنتا";
        B64encoder benco = new B64encoder();
        String enc = benco.encode(original);
        try
        {
            String dec = new String(benco.decode(enc.toCharArray()), "UTF-8");
            PrintStream out = new PrintStream(System.out, true, "UTF-8");
            out.println("Original: " + original);
            prtHx("ara", original.getBytes());
            out.println("Encoded: " + enc);
            prtHx("enc", enc.getBytes());
            out.println("Decoded: " + dec);
            prtHx("dec", dec.getBytes());
        } catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }

控制台的输出如下:

原始数据:خهعسيبنتا
ara = 3F, 3F, 3F, 3F, 3F, 3F, 3F, 3F, 3F
编码后数据:Pz8/Pz8/Pz8/
enc = 50, 7A, 38, 2F, 50, 7A, 38, 2F, 50, 7A, 38, 2F
解码后数据:?????????
dec = 3F, 3F, 3F, 3F, 3F, 3F, 3F, 3F, 3F

prtHx函数将字节的十六进制值写入输出。请问我是否存在明显的错误?


Andreas指出了正确的解决方案,他强调getBytes()方法使用平台默认编码(Cp1252),即使源文件本身是UTF-8编码。通过使用getBytes("UTF-8"),我能够发现编码和解码后的字节实际上是不同的。进一步的调查显示,encode方法也使用了getBytes()方法,更改这一点就可以很好地解决问题。


try
        {
            String enc = benco.encode(original);
            String dec = new String(benco.decode(enc.toCharArray()), "UTF-8");
            PrintStream out = new PrintStream(System.out, true, "UTF-8");
            out.println("Original: " + original);
            prtHx("ori", original.getBytes("UTF-8"));
            out.println("Encoded: " + enc);
            prtHx("enc", enc.getBytes("UTF-8"));
            out.println("Decoded: " + dec);
            prtHx("dec", dec.getBytes("UTF-8"));

        } catch (UnsupportedEncodingException e)
        {
            e.printStackTrace();
        }

系统编码Cp1252
原文: خهعسيبنتا
ori = D8, AE, D9, 87, D8, B9, D8, B3, D9, 8A, D8, A8, D9, 86, D8, AA, D8, A7
编码后: 2K7Zh9i52LPZitio2YbYqtin

enc = 32, 4B, 37, 5A, 68, 39, 69, 35, 32, 4C, 50, 5A, 69, 74, 69, 6F, 32, 59, 62, 59, 71, 74, 69, 6E
解码后: خهعسيبنتا
dec = D8, AE, D9, 87, D8, B9, D8, B3, D9, 8A, D8, A8, D9, 86, D8, AA, D8, A7

谢谢。


字节数组转Base64编码的转换器。 - emt14
1个回答

6

String#getBytes() 方法使用平台默认的字符集来对字符进行编码。字符串字面量 "خهعسيبنتا" 的实际编码是由 java 源文件中“定义”的(当您创建或保存文件时,需要选择一个字符编码)。

这可能是为什么 ara 转换成 0x3f 字节的原因。

可以试试这个方法:

out.println("Original: " + original);
prtHx("ara", original.getBytes("UTF-8"));
out.println("Encoded: " + enc);
prtHx("enc", enc.getBytes("UTF-8"));
out.println("Decoded: " + dec);
prtHx("dec", dec.getBytes("UTF-8"));

谢谢Andreas,你让我找对了方向。在使用UTF-8的getBytes后,我意识到传递给编码器的实际字节与解码的字节不同。原来编码器是使用getBytes()进行编码的。将其更改为getBytes("UTF-8")就解决了问题。 - emt14
你可以使用StandardCharsets.UTF_8常量代替"UTF-8",这样你就可以得到getBytes(StandardCharsets.UTF_8) :) - Monsif EL AISSOUSSI

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接