java 多次以不同字符集编码解码后回不来的问题。
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java 多次以不同字符集编码解码后回不来的问题。相关的知识,希望对你有一定的参考价值。
String a="中";
//一:
a=new String(a.getBytes("UTF-8"), "GBK");
a=new String(a.getBytes("GBK"), "UTF-8");
//二:
a=URLEncoder.encode(a, "UTF-8");
a=URLDecoder.decode(a, "GBK");
a=URLEncoder.encode(a, "GBK");
a=URLDecoder.decode(a, "UTF-8");
这两种写法应该一样吧。。
Q:别人给我的值是new String("中".getBytes("UTF-8"), "GBK"),有没办法将值还原回"中"
a=new String(a.getBytes("UTF-8"), "GBK");
a=new String(a.getBytes("GBK"), "UTF-8");
对于这一种情况,你之所以输出的是乱码是因为a.getBytes("UTF-8")的意思是按"UTF-8"的编码方式把字符串a转换成为字节数组,new String(a.getBytes("UTF-8"), "GBK")的意思是用"GBK"的编码方式来解释a.getBytes("UTF-8")得到的字节数组来生成字符串。而不是用"GBK"的方式来编码。所以当然是输出乱码。
//二:
a=URLEncoder.encode(a, "UTF-8");
a=URLDecoder.decode(a, "GBK");
a=URLEncoder.encode(a, "GBK");
a=URLDecoder.decode(a, "UTF-8");
你可以试一试下面的方式:
a="中";
a=URLEncoder.encode(a, "UTF-8");
a=URLDecoder.decode(a, "UTF-8");
System.out.println(a);
a=URLEncoder.encode(a, "GBK");
a=URLDecoder.decode(a, "GBK");
System.out.println(a);追问
重新问,别人给我的值是new String("中".getBytes("UTF-8"), "GBK"),有没办法将值还原回"中"
追答new String("中".getBytes("UTF-8"), "GBK")这个写法本身就有问题,你想把“中”按UTF-8转换成字节数组,然后用“GBK"的方式解释这个字节数组得到的字符串是什么。若果你实在想要怎么做,你可读一下String源码看一看new String("中".getBytes("UTF-8"), "GBK")是怎么做的,看能不能找到什么方法把它倒过来。
参考技术A 对,一样啊,会存在回不来的问题?我去试试。追问你看下最后的a是什么,采用方法1或者2
追答你编码和解码要用相同的编码集,这样才不会乱码啊。
你用 UTF-8 编码,却用 GBK 解码,肯定会乱码呀。
按照相同的编码集进行编码然后解码,结果不会乱码,我试过了。
重新问,别人给我的值是new String("中".getBytes("UTF-8"), "GBK"),有没办法将值还原回"中"
追答不行,编码和解码的字符集不同。很明显啊这个
参考技术B 一样的,那么你的问题是什么追问重新问,别人给我的值是new String("中".getBytes("UTF-8"), "GBK"),有没办法将值还原回"中"
如何以正确的方式编码和解码字符[重复]
【中文标题】如何以正确的方式编码和解码字符[重复]【英文标题】:How to encode and decode characters in the right way [duplicate] 【发布时间】:2015-12-07 02:23:39 【问题描述】:我正在开发一个使用编码为UTF-8
的网站。
服务端采用Java开发,数据库采用Windows-1252
编码。
如何正确编码字符,以便它们在数据库查看器和客户端都能正确显示?
编辑
代码如下:
Class.forName("com.pervasive.jdbc.v2.Driver");
Connection conn = DriverManager.getConnection("jdbc:pervasive://XXX.XXX.XXX.XXX/TEST","xxxx", "xxxxx");
Statement stmt = conn.createStatement();
String sql = "INSERT INTO MyTest (COL1, COL2) VALUES (99999, 'Ó 456789 ñÑ; ° - + ( _ . - / \\ & <' )";
stmt.executeUpdate(sql);
数据库查看器显示:? 456789 ??; ? - + ( _ . - / \\ & <
而不是Ó 456789 ñÑ; ° - + ( _ . - / \\ & <
当SELECT
被执行时,字符串? 456789 ??; ? - + ( _ . - / \\ & <
被检索
【问题讨论】:
从个人经验来看,在不遭受某种损失的情况下,没有真正的好方法。一种可能的解决方法是让您的数据在数据库中存储编码的 HTML 实体(例如 © 或 € 用于版权徽标),并期望这些在数据库查看器中显示为这样,同时期望在代码中处理它们在 Java 端,并将它们转换为必要的格式。这很糟糕,但它强调了对符合 Unicode 的数据库技术的需求。 @ShotgunNinja 你混淆了 HTMLescaping
和字符集 byte[]
编码,这是完全不同的问题。
不,我不是。这里的目标是在两端都有可显示的字符/代码点,如果我理解正确的话,其中一些超出了 Windows-1252 的可表示范围。虽然 Unicode 是为此而设计的,但在最新版本 12 之前的 Pervasive SQL 服务器中不允许使用它,因此我们需要提出一种不同的解决方案,该解决方案可以在 DB 查看器以及 Java 和更高版本中运行网络。非 Windows-1252 表示的代码点的 HTML 实体编码是一种解决方法,而不是此问题的解决方案。
我认为问题是由于 Oracle pre-10g 和 Pervasive pre-v12 都没有 decent JDBC 实现来正确处理底层数据令人讨厌的情况(即,由单字节代码页表示,但包含多字节字符,就像我之前的经验一样)。
您混淆了Unicode
代码点规范,它不是编码与编码UTF-8
、UTF-16
和UTF-32
和Windows-1252
是所有代表相同Unicode
代码点的编码映射,但略有不同。某些东西如何显示文本是客户端解释它并显示它的问题,而不是数据的来源。
【参考方案1】:
在 Java 中 String
在内部使用 UTF-16
:
如果你有一个普通的 Java String
,你不需要做任何事情,如果你在插入语句中将它作为 String
插入,你的 JDBC 驱动程序会将 Java String
透明地转换为它使用的任何编码。
当您阅读 ResultSet.getString()
时,它会透明地返回 Java String
。
如果不是这种情况,则说明应用程序中的某些内容配置不正确,并且插入的错误数据不是它所说的编码。垃圾进/垃圾出。
当您需要担心编码/解码时:
在将文本数据读/写到只接受byte[]
的文件或套接字时,您只需要担心转换byte[]
编码。
使用代表文本的byte[]
时,您需要使用new String(bytes,Charset)
和byte[] b = string.getBytes(Charset);
分别指定源/目标String
传入和需要传出的任何编码。
永远不要依赖默认编码:
永远不要使用new String(byte[])
或.getBytes()
,它们使用default
编码,因为它可以改变的所有方式对你的代码都是不透明的,所以你得到的都是废话。
微妙的问题是UTF-8
、Windows-1252
和其他几个编码是ASCII
的超集,并且在此范围内也相互重叠。因此,如果您使用default
编码,一切可能看起来工作正常,然后当您摄取/导出一些包含non-ASCII
范围字符的byte[]
时,事情就会爆炸。
总结:
-
切勿使用
byte[]
表示文本,除非某些 API 要求您这样做。
从不依赖默认编码,即使您认为自己知道它是什么。
总是在从byte[]
或byte[]
转换时指定Charset
。
切勿将Charset
编码与URL/URI/HTML/XML
转义混为一谈。
Unicode 不是编码。
【讨论】:
感谢您的回复!这似乎是一个配置问题。请检查上述问题的编辑,以上是关于java 多次以不同字符集编码解码后回不来的问题。的主要内容,如果未能解决你的问题,请参考以下文章
java.util.Base64解码然后编码产生不同的字符串