如何以正确的方式编码和解码字符[重复]

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 ??; ? - + ( _ . - / \\ &amp; &lt; 而不是Ó 456789 ñÑ; ° - + ( _ . - / \\ &amp; &lt;

SELECT被执行时,字符串? 456789 ??; ? - + ( _ . - / \\ &amp; &lt;被检索

【问题讨论】:

从个人经验来看,在不遭受某种损失的情况下,没有真正的好方法。一种可能的解决方法是让您的数据在数据库中存储编码的 html 实体(例如 © 或 € 用于版权徽标),并期望这些在数据库查看器中显示为这样,同时期望在代码中处理它们在 Java 端,并将它们转换为必要的格式。这很糟糕,但它强调了对符合 Unicode 的数据库技术的需求。 @ShotgunNinja 你混淆了 HTML escaping 和字符集 byte[] 编码,这是完全不同的问题。 不,我不是。这里的目标是在两端都有可显示的字符/代码点,如果我理解正确的话,其中一些超出了 Windows-1252 的可表示范围。虽然 Unicode 是为此而设计的,但在最新版本 12 之前的 Pervasive SQL 服务器中不允许使用它,因此我们需要提出一种不同的解决方案,该解决方案可以在 DB 查看器以及 Java 和更高版本中运行网络。非 Windows-1252 表示的代码点的 HTML 实体编码是一种解决方法,而不是此问题的解决方案 我认为问题是由于 Oracle pre-10g 和 Pervasive pre-v12 都没有 decent JDBC 实现来正确处理底层数据令人讨厌的情况(即,由单字节代码页表示,但包含多字节字符,就像我之前的经验一样)。 您混淆了Unicode 代码点规范,它不是编码与编码UTF-8UTF-16UTF-32Windows-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-8Windows-1252 和其他几个编码是ASCII 的超集,并且在此范围内也相互重叠。因此,如果您使用default 编码,一切可能看起来工作正常,然后当您摄取/导出一些包含non-ASCII 范围字符的byte[] 时,事情就会爆炸。

总结:

    切勿使用 byte[] 表示文本,除非某些 API 要求您这样做。 从不依赖默认编码,即使您认为自己知道它是什么。 总是在从byte[]byte[] 转换时指定Charset切勿Charset 编码与URL/URI/HTML/XML 转义混为一谈。 Unicode 不是编码。

【讨论】:

感谢您的回复!这似乎是一个配置问题。请检查上述问题的编辑,

以上是关于如何以正确的方式编码和解码字符[重复]的主要内容,如果未能解决你的问题,请参考以下文章

如何解码一个unicode字符串Python [重复]

UnicodeEncodeError:'ascii'编解码器无法对特殊名称的字符进行编码[重复]

UnicodeEncodeError:“charmap”编解码器无法编码字符“\u2010”:字符映射到 <undefined> [重复]

UnicodeEncodeError:'ascii'编解码器无法在位置 3 编码字符 u'\ufffd':序数不在范围内(128)[重复]

编码特殊字符以传入url并由javascript读取[重复]

如何解码收到的电子邮件主题行的UTF8字符集[重复]