如何以正确的方式编码和解码字符[重复]
Posted
技术标签:
【中文标题】如何以正确的方式编码和解码字符[重复]【英文标题】: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 不是编码。
【讨论】:
感谢您的回复!这似乎是一个配置问题。请检查上述问题的编辑,以上是关于如何以正确的方式编码和解码字符[重复]的主要内容,如果未能解决你的问题,请参考以下文章
UnicodeEncodeError:'ascii'编解码器无法对特殊名称的字符进行编码[重复]
UnicodeEncodeError:“charmap”编解码器无法编码字符“\u2010”:字符映射到 <undefined> [重复]
UnicodeEncodeError:'ascii'编解码器无法在位置 3 编码字符 u'\ufffd':序数不在范围内(128)[重复]