0

我在向 IIS 服务器发出 HTTP 请求的 Java 应用程序中遇到了一些编码问题。

遍历URLConnection对象的标题,我可以看到以下(相关)标题:

Transfer-Encoding: [chunked]
Content-Encoding: [utf-8]
Content-Type: [text/html; charset=utf-8]

URLConnection.getContentEncoding()方法返回 utf-8 作为文档编码。

这就是我的 HTTP 请求和流读取的方式:

OutputStreamWriter sw = null;
BufferedReader br = null;
char[] buffer = null;
URL url;
url = new URL(this.URL);
URLConnection connection = url.openConnection();
connection.setDoOutput(true);
sw = new OutputStreamWriter(connection.getOutputStream());
sw.write(postData);
sw.flush();
br = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF8"));
StringBuilder totalResponse = new StringBuilder();
String line;

while((line = br.readLine()) != null) {
    totalResponse.append(line);
}
buffer = totalResponse.toString().toCharArray();
if (sw != null)
    sw.close();

if (br != null)
    br.close();

return buffer;

但是,服务器“ÃÃÃção”发送的以下字符串被客户端接收为“�����o”。

我究竟做错了什么 ?

4

4 回答 4

1

根据您的评论,您正尝试从 IIS 服务器接收 FIX 消息,而 FIX 使用 ASCII。只有一小部分标签支持其他编码,它们必须以特殊方式处理(标准 FIX 规范中的非 ASCII 标签是 349,351,353,355,357,359,361,363,365)。如果存在此类标签,您将获得一个标签 347,其中包含一个指定编码的值(例如 UTF-8),然后每个标签前面都会有一个标签,为您提供即将到来的编码值的长度(对于标签 349,你总是会先得到 348 的整数值)

在您的情况下,看起来服务器正在以其他编码发送自定义标签 10411(10xxx 范围)。按照惯例,前面的标签 10410 应该给你 10411 中值的长度,但它包含“0000”,这可能有其他含义。

请注意,尽管 FIX 消息可读性很强,但仍应将它们视为二进制数据。标签和值大多是 ASCII 字符,但分隔符 (SOH) 是 0x01,如上所述,某些标签可能使用另一种编码进行编码。IIS 服务应该真正返回数据,application/octet-stream以便可以正确接收。试图退回它text/html是自找麻烦:)。

于 2014-10-03T05:28:04.667 回答
0

您可以尝试将流作为请求属性的一部分,然后在客户端打印出来。将按原样接收请求属性,没有任何编码问题

于 2014-10-07T06:22:51.980 回答
0

如果服务器真的发送了“UTF-8”的Content-Encoding,那就混乱了。见http://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7231.html#header.content-encoding

于 2014-10-02T11:32:13.843 回答
0

为了获得良好的订单,请进行一些更正。

    URLConnection connection = url.openConnection();
    connection.setDoOutput(true);
    connection.connect();
    try (Writer sw = new OutputStreamWriter(connection.getOutputStream(),
                StandardCharsets.UTF_8)) {
        sw.write(postData);
        sw.flush();

        try (BufferedReader br = new BufferedReader(
                new InputStreamReader(connection.getInputStream(),
                StandardCharsets.UTF_8))) {
            StringBuilder totalResponse = new StringBuilder();
            String line;
            while ((line = br.readLine()) != null) {
                totalResponse.append(line).append("\r\n");
            }
            return totalResponse.toString().toCharArray();
        } // Close br.
    } // Close sw.

也许:

postData =  ... + "Accept-Charset: utf-8\r\n" + ...;

收到totalResponse.toString()你应该都正确阅读。

但是当再次显示时,字符串/字符再次转换为字节,并且编码失败。例如 System.out.println 可能不会使用 Windows 编码。

您可以通过转储字节来测试字符串:

String s = totalResponse.toString();
Logger.getLogger(getClass().getName()).log(Level.INFORMATION, "{0}",
    Arrays.toString(s.getBytes(StandardCharsets.UTF_8)));

在极少数情况下,字体不会包含特殊字符。

于 2014-10-02T12:11:48.287 回答