我正在运行一个Servlet,它接收来自不一定用UTF-8编码的网站的POST请求。这些请求用GSON解析,信息(主要是字符串)最终出现在对象中。
客户端字符集似乎没有用于任何此类字符串,因为Java只是在内部以字符串形式存储字符串。
现在,如果发送请求的页面具有非unicode-charset,则字符串中的信息会出现乱码并且不代表发送的内容 - 它似乎在某个地方被错误解释,无论是在被字符串化的过程中servlet,或由gson解析。
假设没有简单的方法来修复问题的根源,是否有一种方法可以恢复该信息,因为使用了(错误解释的)Java字符串和charset标识符(即“Shift_JIS”,“Windows-1255”)在客户端显示它?
答案 0 :(得分:2)
我之前没有必要这样做,但我相信
final String realCharsetName = "Shift_JIS"; // for example
new String(brokenString.getBytes(), realCharsetName);
很有可能做到这一点。
(但这确实假设在阅读时完全忽略了编码问题,因此使用了平台的默认字符集(这可能是假设,因为如果人们想到字符集,他们可能会把它弄好)。它还假设你'在具有与最初读取字节并创建字符串的默认字符集相同的机器上重新解码。)
如果您碰巧确切地知道哪个字符集被错误地用于读取字符串,您可以将其传递到getBytes()
调用以使其100%可靠。
答案 1 :(得分:2)
假设它是以下列方式获得的POST请求参数
String string = request.getParameter("name");
然后您需要使用服务器本身用于解码参数值的字符集将字符串URL编码回原始查询字符串参数值
String original = URLEncoder.encode(string, "UTF-8");
然后使用预期的字符集
对其进行URL解码String fixed = URLDecoder.decode(original, "Shift_JIS");
作为更好的选择,您还可以指示服务器在通过ServletRequest#setCharacterEncoding()
获取任何请求参数之前直接使用给定的字符集。
request.setCharacterEncoding("Shift_JIS");
String string = request.getParameter("name");
顺便说一句,没有办法知道客户端用来对POST请求体进行URL编码的字符集。几乎没有客户端在Content-Type
请求头中指定它,否则ServletRequest#setCharacterEncoding()
调用将基于此隐式地由servlet API完成。您可以通过选中getCharacterEncoding()
来确定它,如果它返回null
,那么客户端已指定无。
但是,如果客户端已将值正确编码为UTF-8或任何其他字符集,则这当然不起作用。 Shift_JIS
按摩会再次打破它。存在基于获得的字节序列猜测原始字符集的工具/ API,但这不是100%可靠的。如果您的servlet涉及公共API,那么只要在请求标头中未指定字符集,您就应该记录以使仅接受UTF-8编码参数。然后,您可以将问题移至客户端并指出他们的错误。
答案 2 :(得分:0)
解决问题的正确方法是确保在阅读内容时使用正确的字符编码。大多数框架和库都会为您解决这个问题,但是如果您手动编写servlet,那么您需要注意这一点。这不是Java的缺点。你只需要注意编码。具体来说,Content-Type标头应包含有用的信息。
每次在Java中将字节流转换为字符流时,都应提供字符编码,以便可以将字节正确解码为字符。例如,参见InputStreamReader构造函数。
答案 3 :(得分:0)
我是否更正你得到的是一个被解析的字符串,好像它是UTF-8但是在Windows-1255中编码了?解决方案是将您的字符串编码为UTF-8并将结果解码为Windows-1255。