我在向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”。
我做错了什么?
答案 0 :(得分: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
返回是一个问题:)。
答案 1 :(得分:0)
如果服务器确实发送了内容编码" UTF-8"然后它非常混淆。见http://svn.tools.ietf.org/svn/wg/httpbis/specs/rfc7231.html#header.content-encoding
答案 2 :(得分: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()
您应该正确阅读。
但是当再次显示时,String / char再次转换为字节,那里编码失败。例如System.out.println不会这样做,因为可能使用了Windows编码。
您可以通过转储字节来测试字符串:
String s = totalResponse.toString();
Logger.getLogger(getClass().getName()).log(Level.INFORMATION, "{0}",
Arrays.toString(s.getBytes(StandardCharsets.UTF_8)));
在极少数情况下,字体不会包含特殊字符。
答案 3 :(得分:0)
您可以尝试将流作为请求属性的一部分,然后在客户端打印出来。如果遇到任何编码问题,将收到请求属性