繁体   English   中英

读取InputStream时忽略编码

[英]Encoding ignored while reading InputStream

我在向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”接收。

我究竟做错了什么 ?

根据您的评论,您尝试从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返回会带来麻烦:)。

如果服务器确实发送了“ UTF-8”的内容编码,则非常困惑。 参见http://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7231.html#header.content-encoding

为了获得良好的状态,需要进行一些更正。

    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)));

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

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

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM