2

我解决了检索和显示非 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

这是为什么?

4

2 回答 2

2

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

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

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

于 2013-07-01T19:47:05.790 回答
1

尝试下一个:

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
于 2013-06-27T17:38:08.780 回答