java中的utf-8解码

时间:2009-10-29 08:30:22

标签: java encoding utf-8 groovy

我正在尝试将参数从PHP中间层传递到了解J2EE的java后端。我正在用Groovy编写控制器代码。在那里,我正在尝试解码一些可能包含国际字符的参数。

到目前为止,我对调试此问题的结果感到非常困惑,因此我希望与您分享,希望有人能够对我的结果给出正确的解释。

为了我的小测试,我传递的参数是“déjeuner”。只是为了确定,System.out.println(“déjeuner”)正确地给了我:

déjeuner
控制台中的

以下是原始字符串的每个字符的char / dec和hex值:

next char: d 100 64
next char: ? -61 c3
next char: ? -87 a9
next char: j 106 6a
next char: e 101 65
next char: u 117 75
next char: n 110 6e
next char: e 101 65
next char: r 114 72

请注意,UTF-8中的c3a9序列是所希望的角色:http://www.fileformat.info/info/unicode/char/00e9/index.htm

现在,如果我尝试将此字符串作为UTF-8字符串读取,就像在stmt.getBytes(“UTF-8”)中一样,我突然得到一个11字节的序列,如下所示:

64 c3 83 c2 a9 6a 65 75 6e 65 72

而stmt.getBytes(“iso-8859-1”)给了我9个字节:

64 c3 a9 6a 65 75 6e 65 72

请注意c3a9序列!

现在如果我尝试将UTF-8序列转换为UTF-8,就像在

中一样
new String(stmt.getBytes("UTF-8"), "UTF-8");

我明白了:

next char: d 100 64
next char: ? -61 c3
next char: ? -87 a9
next char: j 106 6a
next char: e 101 65
next char: u 117 75
next char: n 110 6e
next char: e 101 65
next char: r 114 72

注意c3a9序列

,而

new String(stmt.getBytes("iso-8859-1"), "UTF-8")

结果:

next char: d 100 64
next char: ? -23 e9
next char: j 106 6a
next char: e 101 65
next char: u 117 75
next char: n 110 6e
next char: e 101 65
next char: r 114 72

注意e9中的utf-8(和ascii)再次是我渴望的'é'字符。

不幸的是,在任何一种情况下,我最终都会得到一个正确的字符串,就像文字字符串“déjeuner”一样。奇怪的是,字节序列似乎都是正确的。

4 个答案:

答案 0 :(得分:9)

在处理字符串时,请始终记住:byte!= char。因此,在您的第一个示例中,您有char c3,而不是byte c3,这是一个巨大的差异:byte将是UTF-8序列的一部分,但char 已经是Unicode 。因此,当您将其转换为UTF-8时,Unicode字符c3必须成为byte序列c3 83

所以问题是:你是如何获得String的?该代码中必定存在一个错误,该错误无法正确处理UTF-8编码的byte序列。

ISO-8859-1通常有效的原因是此编码不会修改任何char代码点< 256(即0到255之间的任何值),因此不会修改UTF-8编码的byte序列。

您的上一个示例也是错误的:char e9ISO-8859-1中的é和Unicode。在UTF-8中,它不是有效的,因为它不是byte,因为缺少byte c3前缀。也就是说,它正确表示您寻找的Unicode字符串。

答案 1 :(得分:1)

如果您从"d\u00C3\u00A9jeuner".equals(stmt)的Java字符串开始,那么此阶段的数据已经损坏。

Java char不是C char。 Java中的char为16位宽,隐式包含UTF-16个编码数据。尝试将任何其他编码数据存储在Java char / String类型中是一件麻烦事。任何其他编码中的字符数据应为byte数据。

如果您正在阅读parameter using the servlet API,则HTTP请求可能包含不一致或不足的编码信息。检查调用代码和HTTP标头。客户端可能将数据编码为 UTF-8 ,但servlet将其解码为 ISO-8859-1

答案 2 :(得分:0)

我有一个非常类似的问题,除了我的表单使用“GET”请求而不是“POST”请求。

所以,我的网址类似于:http://localhost:4502/form.jsp?query=d%C3%A9jeuner

request.getCharacterEncoding() = ISO-8859-1
response.getCharacterEncoding() = UTF-8
request.getParameter("query") = déjeuner

HttpServletRequest应该使用UTF-8来解码请求参数(显然它不是)或者这只是一个浏览器错误,因为浏览器没有设置任何字符编码标题(这也没有多大意义,因为它是没做帖子请求)。以下是完整的标题集,并注意URL中的%C3%A9。

http://localhost:4502/form.jsp?query=d%C3%A9juerne

GET /form.jsp?query=d%C3%A9juerne HTTP/1.1
Host: localhost:4502
User-Agent: Mozilla/5.0 (X11; U; Linux i686; en-GB; rv:1.9.0.17) Gecko/2010010604 Ubuntu/9.04 (jaunty) Firefox/3.0.17
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-gb,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 300
Connection: keep-alive

我遇到的这个问题是我实际上将查询复制并粘贴到浏览器表单中并且错误地对其进行了编码。在chrome和firefox中都有。

答案 3 :(得分:0)

经过进一步调查后,我找到了这个答案

How to get UTF-8 working in Java webapps?

关于在tomcat连接器中设置URIEncoding =“UTF-8”的全部内容。

现在要弄清楚如何在CMS中使用(CQ5 / Day)。