在我的应用程序中,我收到一个URL-UTF8编码的字符串,由发送客户端分割。拆分后,每个消息部分都包含一些标题信息,用于重建消息。
使用英文字符,非常简单
String content = new String(request.getParameter("content").getBytes("UTF-8"));
我将其与标题信息一起存储在缓冲区中,用于每个接收到的部分。收到所有部分后,我只需根据标题信息连接每个部分重构消息。
对于使用16位编码的语言,这有时无法按预期工作。如果拆分不发生在单个字符的中间,那么一切正常。
例如,这是由客户发送的三个希伯来字符串:
%D7%93%D7%99%D7%91
如果结果如下:{%D7%93%D7%99} {%D7%91},重建不是问题。
然而,有时客户将其分成中间(例如:{%D7%93%D7} {%99%D7%91})
当发生这种情况时,重建后我会在边界点处获得两个 字符,而不是单个正确的希伯来字符。
我认为无法正确保留单字节信息与传递字符串有关,所以我尝试将字节数组从request.getParameter(“content”)。getBytes(“UTF-8”)传递到缓冲区而不用包装在字符串连接在一起的字符串数组。在缓冲区中,我在将最终数组转换为字符串之前加入了所有这些数组。
即使在这样做之后,我仍然“丢失”了由单个字节保存的信息。我猜这是因为getBytes(“UTF-8”)方法无法正确解析单个字节,因为它们不是有效字符。是吗?
有什么方法可以绕过这个并保留这些尾部/头部字节?
答案 0 :(得分:3)
您的客户是这里的问题。显然,它将文本数据视为字节数组,以便将其拆分,然后将无效片段作为文本发送(HTTP请求参数本质上是文本的)。那时,你已经输了。
您必须更改客户端以将数据拆分为文本(即沿字符边界),或更改协议以将片段作为二进制数据发送,即不作为参数发送,而是作为请求正文,通过ServletRequest.getInputStream()
- 然后,在解码之前连接数据应该有效。
(警告:上面假设您确实在编写Servlet代码,我从request.getParameter()
方法推断出来;但即使这是巧合,同样的原则也适用:在任何转换之前将数据拆分为String to byte []发生在客户端,或者确保在任何转换为String之前连接服务器上的字节数组。)
答案 1 :(得分:0)
您必须首先收集所有字节,然后将它们全部转换为字符串。
答案 2 :(得分:0)
以下方案是一个黑客,但它应该适用于你的情况,
在Latin-1模式下设置服务器/页面。如果这是GET,则客户端无法设置编码。你必须在服务器端执行此操作。例如,您需要在Tomcat的连接器中添加URIEncoding="iso-8859-1"
。
获取内容为Latin1。在这一点上它将是错误的值,但不要担心,
String content = request.getParameter(“content”);
将字符串连接为Latin-1。
data = data + content;
当你得到整件事时,你需要将字符串重新编码为UTF-8,
String value = new String(data.getBytes(“iso-8859-1”),“utf-8”);
value
应包含正确的字符。
答案 3 :(得分:-1)
你永远不需要将字符串转换为字节然后转换为String java,这是完全没有意义的。一旦一系列字节被解码为String,它就是Java字符串编码(我认为是UTF-16E)。
您遇到的问题是应用程序服务器正在对传入的HTTP请求(通常是平台编码)的编码做出假设。在其他任何调用getParameter()
之前,您可以通过调用ServletRequest.setCharacterEncoding(String)
向应用程序服务器提供有关预期编码的提示。
浏览器假定应使用与提供页面相同的编码将表单字段提交回服务器。这是一般规则,因为HTTP规范没有办法指定传入请求的编码,只有响应。
Spring有一个很好的过滤器可以为你CharacterEncodingFilter执行此操作,如果你将其定义为web.xml中的每个第一个过滤器,那么大多数编码问题都会消失。