org.apache.commons.codec.DecoderException:奇数个字符

问题描述 投票:0回答:5

在 url 参数中发送十六进制字符串并尝试在服务器端将其转换为字符串。 使用以下 javascript 编码代码转换用户输入的字符串

function encode(string) {
    var number = "";
    var length = string.trim().length;
    string = string.trim();
    for (var i = 0; i < length; i++) {
        number += string.charCodeAt(i).toString(16);
    }
    return number;
}

现在我正在尝试在java代码中解析十六进制字符串

419
为俄语字符
Й
,如下

byte[] bytes = "".getBytes();
     
try {
    bytes = Hex.decodeHex(hex.toCharArray());
    sb.append(new String(bytes,"UTF-8"));
} catch (DecoderException e) {      
    e.printStackTrace(); // Here it gives error 'Odd number of characters'
} catch (UnsupportedEncodingException e) {           
    e.printStackTrace();
}

但它给出以下错误

"org.apache.commons.codec.DecoderException: Odd number of characters." 

如何解决。由于许多俄语字符具有 3 位十六进制代码,因此无法将其转换为

.toCharArray()

javascript java encode
5个回答
0
投票

改用 Base64

val aes = KeyGenerator.getInstance("AES")
aes.init(128)
val secretKeySpec = aes.generateKey()
val base64 = Base64.encodeToString(secretKeySpec.encoded, 0)
val bytes = Base64.decode(base64, 0)
SecretKeySpec(bytes, 0, bytes.size, "AES") == secretKeySpec

0
投票

在您提到的 Й 是 U+0419 的情况下,大多数西里尔字符以前导 0 开头。这显然意味着在转换之前在奇数字符数组之前添加 0 会有所帮助。

测试javascript似乎这仅对于1个字母长的字符串来说是安全的:Ѓ(U+0403)返回403,Ѕ(U+0405)返回405,但是ЃЅ返回403405而不是04030405或4030405,这更糟糕,因为它是偶数,不会触发异常,并且可以解码为完全不同的东西。

This 处理用前导零填充的问题可能有助于 javascript 部分。


0
投票

您好,您可以使用 Unicode 编码。在您的情况下,字符

Й
将在客户端转换为
\u0419
。然后在服务器端你可以使用 Java,如下所示:

import org.apache.commons.lang.StringEscapeUtils;

// Russian char = "Й"
String hex = "\u0419";
String unescapeJava = StringEscapeUtils.unescapeJava(hex);

System.out.println("unescapeJava => " + unescapeJava);


0
投票

问题出在这一行:

number += string.charCodeAt(i).toString(16);

当循环到达字符“Й”时,

string.charCodeAt(i)
返回十进制的 1049,但是当您将其转换为十六进制(基数 16)时,它会变成“419”,您可以直接追加它。将字符代码附加到 0x80 恰好是正确的,但超出此点就不正确。 在这种情况下,您想要附加的是根据 UTF-8 规范的字符的 2 字节编码。维基百科有一个很好的总结和一些关于如何正确编码 UTF-8 文本的示例:https://en.wikipedia.org/wiki/UTF-8

这个链接解释了如何在js中从字符串获取UTF-8字节数组:如何将UTF8字符串转换为字节数组?


-3
投票

而不是

    sb.append(new String(bytes,"UTF-8"));

试试这个

    sb.append(new String(bytes,"Windows-1251"));
© www.soinside.com 2019 - 2024. All rights reserved.