OutputStreamWriter的flush方法在尝试写入汉字时抛出IOException

发布于 2024-10-12 18:29:05 字数 1304 浏览 8 评论 0原文

下面是我用来在 Android 应用程序中发送 SOAP 请求的代码,它可以很好地处理除一个请求之外的所有请求。当 requestBody 变量中存在中文字符时,此代码会在 wr.flush(); 上抛出 IOException : Content-length超过

在这种情况下,内容长度是 409

            URL url = new URL(Constants.HOST_NAME);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            // Modify connection settings
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
            connection.setRequestProperty("SOAPAction", soapAction);

            String requestBody = new String(soapRequest.getBytes(),"UTF-8");
            int lngth = requestBody.length();
            connection.setRequestProperty("Content-Length", (""+lngth));

            // Enable reading and writing through this connection
            connection.setDoInput(true);
            connection.setDoOutput(true);

            // Connect to server
            connection.connect();

            OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
            wr.write(requestBody);
            wr.flush();
            wr.close();

当字符串中存在中文字符时,有什么线索会出现问题吗?

编辑:我已经删除了“内容长度”标头字段并且它有效,但为什么呢?

Below is the code I am using to send SOAP requests in my Android app and it works fine with all requests except one. This code throws IOException : Content-length exceeded on wr.flush(); when there are chinese characters in requestBody variable.

The content-length in that case is 409

            URL url = new URL(Constants.HOST_NAME);
            HttpURLConnection connection = (HttpURLConnection) url.openConnection();

            // Modify connection settings
            connection.setRequestMethod("POST");
            connection.setRequestProperty("Content-Type", "text/xml; charset=utf-8");
            connection.setRequestProperty("SOAPAction", soapAction);

            String requestBody = new String(soapRequest.getBytes(),"UTF-8");
            int lngth = requestBody.length();
            connection.setRequestProperty("Content-Length", (""+lngth));

            // Enable reading and writing through this connection
            connection.setDoInput(true);
            connection.setDoOutput(true);

            // Connect to server
            connection.connect();

            OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");
            wr.write(requestBody);
            wr.flush();
            wr.close();

Any clue what is going wrong when there are chinese characters in the string?

EDIT: I have removed the 'content-lenght' header field and it works, but why?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

离不开的别离 2024-10-19 18:29:05

此代码将请求的 Content-Length 属性设置为消息的字符串表示形式中的字符数:

String requestBody = new String(soapRequest.getBytes(),"UTF-8");
int lngth = requestBody.length();
connection.setRequestProperty("Content-Length", (""+lngth));

但随后您在写入之前将该字符串表示形式转换回字节:

OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");

因此,您最终会写入比您声明的字节更多的字节。对于任何非 ASCII 字符,您都会遇到同样的问题。相反,您应该执行类似的操作(复制粘贴,因此可能存在语法错误):

byte[] message = soapRequest.getBytes();
int lngth = message.length;
connection.setRequestProperty("Content-Length", (""+lngth));

// ...

connection.getOutputStream().write(message);

This code sets the request's Content-Length property to the number of characters in the string representation of the message:

String requestBody = new String(soapRequest.getBytes(),"UTF-8");
int lngth = requestBody.length();
connection.setRequestProperty("Content-Length", (""+lngth));

But then you convert that string representation back to bytes before writing:

OutputStreamWriter wr = new OutputStreamWriter(connection.getOutputStream(), "UTF-8");

So you end up writing more bytes then you've claimed. You'll run into the same problem with any non-ASCII characters. Instead, you should do something like this (copy-and-paste, so may have syntax errors):

byte[] message = soapRequest.getBytes();
int lngth = message.length;
connection.setRequestProperty("Content-Length", (""+lngth));

// ...

connection.getOutputStream().write(message);
网白 2024-10-19 18:29:05

为了简化另一个答案:Content-Length 必须是以字节为单位的长度,并且您以字符(Java 的 16 位字符类型)指定长度。一般来说,这些是不同的。由于 UTF-8 是一种可变字节长度编码,因此超出基本 7 位 ASCII 范围的任何内容都存在差异。另一个答案显示了编写代码的正确方法。

To simplify the other answer: Content-Length MUST be length in bytes, and you are specifying length in chars (Java's 16-bit char type). These are different, in general. Since UTF-8 is a variable-byte-length encoding, there is difference for anything beyond basic 7-bit ASCII range. The other answer shows proper way to write code.

要走就滚别墨迹 2024-10-19 18:29:05

我的猜测是你没有将中文转换为utf-8。如果您支持用户在字段中输入双宽和扩展字符集,则需要确保将输入从这些字符集(ASCII、UNICODE 或 UCS)转换为 UTF-8。

一旦确定了正在使用的字符编码,您可以使用以下内容:

FileInputStream(inputFile), "inputencoding");
Writer output = new OutputStreamWriter(new FileOutputStream(outputFile), "outputencoding");

参考

创建用于读/写的流以在两者之间进行转换时。

另一种选择是研究设置控制 http 请求语言的请求属性。我对此了解不多。

My guess is that you have not converted the chinese to utf-8. If you support users entering doublewide and extended character sets into your fields, you'll need to make sure to convert your inputs from those character sets (ASCII, UNICODE or UCS) to UTF-8.

Once you determine the character encodings you are working with, you can use something like:

FileInputStream(inputFile), "inputencoding");
Writer output = new OutputStreamWriter(new FileOutputStream(outputFile), "outputencoding");

Reference

when creating your streams for reading/writing to convert between two.

Another alternative is to look into setting the request property controlling the language of the http request. I do not know much about that.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文