【问题标题】:Http GET of source containing non-UTF-8 characters包含非 UTF-8 字符的源的 Http GET
【发布时间】:2013-06-27 17:22:42
【问题描述】:

我解决了我在检索和显示非 UTF-8 字符时遇到的问题,但我不明白为什么我的解决方案有效。

以下代码:

final HttpClient client = new HttpClient();
final HttpMethod method = new GetMethod(urlString);
client.executeMethod(method);
final String responseBodyAsString = method.getResponseBodyAsString();
System.out.println(responseBodyAsString);

弄乱了显示屏上的一些字符,例如 Yáñez

我变了:

final String responseBodyAsString = method.getResponseBodyAsString();

final ByteBuffer inputBuffer = ByteBuffer.wrap(method.getResponseBody());
final String responseBodyAsString = new String(inputBuffer.array());

和以前相同的字符串正确地表示为 Yáñez

这是为什么呢?

【问题讨论】:

  • 请求服务器发送UTF-8数据的正确方法是使用Accept-Charset: utf-8请求头,而不是Content-Type请求头。
  • 最重要的是,正确的方法是不要更改字符。许多人认为“哦,这只是一个带有波浪线的 n”,但实际上它是一个不同的字母。如果某些软件将 Q 更改为 O,您会怎么想“嗯,它只是带有波浪线的 O”
  • @RemyLebeau 查看我的更新,它解决了这个问题。我不必指定字符集或内容类型。这是因为 httpclient 有一些机制可以知道使用什么字符?
  • @MihaiNita 要点:添加字符有充分的理由,删除它们并不理想。如果我们坚持使用 UTF-8,我无法对西班牙语发表评论,但在法语中,将 ç、é 等字母更改为 c 和 e 是一个错误,但仍然是可用的最佳方法。因此,如果有人没有 Q,那么是的,O 可以合理地回答您的问题。话虽如此,在当前示例中,我能够解决我的问题并正确显示字符。

标签: java utf-8 character-encoding get


【解决方案1】:

getResponseBodyAsString() 使用 HTTP 响应的 Content-Type 标头来了解响应正文的字符集是什么,因此可以根据需要将数据转换为 StringgetResponseBody() 只是按原样返回正文的原始字节,然后使用平台的默认字符集将其转换为 String。由于您可以通过手动转换原始字节来获得所需的String 输出,这表明 HTTP 服务器根本没有在响应的Content-Type 标头中指定字符集,或者指定了错误的字符集。

YáñezYáñez 的UTF-8 编码版本,因此String(bytes[]) 构造函数能够正确解码它是很奇怪的,除非平台的默认字符集实际上是UTF-8。如果使用的响应字符集是 ISO-8859-1,则 getResponseBodyAsString() 返回 Yáñez 确实有意义,这是根据 RFC 2616 第 3.7 节在未明确指定字符集时通过 HTTP 发送的 text/... 媒体类型的默认字符集。 1.

在怀疑getResponseBodyAsString() 存在错误之前,我建议在发送数据的服务器脚本中查找错误(或向服务器管理员报告错误报告)。您可以使用 Wireshark 之类的数据包嗅探器或 Fiddler 之类的调试代理来确认响应 Content-Type 标头中缺少/无效的字符集。

【讨论】:

  • 很好的解释,谢谢。我做了 wget -d 并看到了您的怀疑:响应中未指定字符集:“Accept-Ranges:字节... Content-Type:text/xml”。我不理解您的评论,除非平台是 UTF-8,否则 String(bytes[]) 正确解码很奇怪。会不会适得其反? IE。仅当平台支持能够显示 Yáñez 的集合时,它才会起作用吗?我在 Mac 上使用 Eclipse 运行我的代码,仅供参考。
【解决方案2】:

尝试下一个:

private static final String UNICODE = "ÀàÈèÌìÒòÙùÁáÉéÍíÓóÚúÝýÂâÊêÎîÔôÛûŶŷÃãÕõÑñÄäËëÏïÖöÜüŸÿÅåÇçŐőŰű";
private static final String PLAIN_ASCII = "AaEeIiOoUuAaEeIiOoUuYyAaEeIiOoUuYyAaOoNnAaEeIiOoUuYyAaCcOoUu";

public static String convertNonAscii(String str) {
    if (str == null) {
        return null;
    }
    StringBuilder sb = new StringBuilder();
    for (int i = 0; i < str.length(); i++) {
        char c = str.charAt(i);
        int pos = UNICODE.indexOf(c);
        if (pos > -1)
            sb.append(PLAIN_ASCII.charAt(pos));
        else {
            sb.append(c);
        }
    }
    return sb.toString();
}

public static void main(String[] args) {
    Pattern p = Pattern.compile("[^\\x00-\\x7E]", Pattern.CASE_INSENSITIVE);
    System.out.println(p.matcher(UNICODE).find());
    System.out.println(p.matcher(PLAIN_ASCII).find());
    System.out.println(convertNonAscii("ú or ñ"));
}

输出:

true
false
u or n

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2020-03-07
    • 2012-02-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-06-04
    • 2018-09-21
    相关资源
    最近更新 更多