`

(转)JDBC与字符集总结

    博客分类:
  • jdbc
阅读更多

http://tech.ccidnet.com/art/3737/20051007/472823_1.html

JDBC与字符集总结

发布时间:2006.03.10 07:40      来源:CSDN     作者:

 


JDBC与字符集总结
danci.z(小谢), 2003.11.16

 

过JDBC访问数据库时遇到的字符集问题中,可以归纳为如下因素:

 

- JVM对字符集的处理

 

JVM核心完全使用Unicode字符集,编码上采用UTF-16LE(x86和Unix)。 Java编译器扫描.java源文件时将完成预转换,比如在中文Windows上编译.java文件时,你可能已经注意到.java文件中的字符串和.class中的不一样。因为.java文件本身用的是gb2312编码,而.class内则是UTF-16LE编码。如果你的编辑器支持,你可能会选择直接用UTF-8来书写.java源程序,这时Java编译器就会用UTF-8对源程序解码。

 

在输出时,比如调用System.out.print方法也将完成一个编码转换,在上述情况中经常是将内存中的UTF-16LE编码的字串转换成控制台上可读的gb2312编码。

 


- JSP页面使用的字符集

 

运行JSP页面前总会被预处理至.java程序并被编译成.class,注意到JSP总是一个servlet,因此实际上这里存在两个字符集,一是.jsp文件本身使用的字符集,另一则是servlet输出内容的字符集(content-type)。尽量使.jsp文件本身的字符集和输出内容的字符集保持一致,比如一致采用UTF-8。Response的实现将jvm中的UTF-16LE字串转换至<%@page encoding=...%>所指定的编码,

 


- Connection 使用的字符集

 

连接的字符集限制了SQL语句可以使用的字符。这在UTF-16中格外明显,如果连接不使用UTF-16的字符集,那么由于大多数的Latin-1字符集对'\0'的处理将使大多数SQL语句成为无效语句,比如SELECT语句通过UTF-16LE编码后将变成"S\0E\0L\0E\0C\0T\0...",服务器的SQL分析器在遇到第一个'\0'便认为语句已经结束。
 
但仍然可以将UTF-16LE编码的字串送入Latin-1字符集的连接,方法是SQL语句本身仍采用Latin-1编码,而相关的字串(引号内部的)采用UTF-16LE。这种情况下,UTF-16LE的字串不能包括Unicode字符集中编码小于256的字符(包括拉丁字母和数字、英文符号),否则SQL分析器会报告"字符串未结束"之类的错误。(为什么?)

 

- 数据库系统

 

并不是所有数据库都支持Unicode,你可能有必要通过字符集转换来保存一些特殊的字符数据。如果数据库仅支持Latin-1字符集(这样的系统不在少数),对于中文的情况,你可以将字符串用Latin-1编码,然后用gb2312解码,觉得困惑?如果你(曾经)是C++程序员,那么这里的编码类似于dynamic_cast, 而解码则相当于reinterpret_cast。

 

 sql_str = new String( java_str.getBytes("ISO-8859-1"), "gb2312" );

 

在获取数据的时候则刚好相反:

 

 java_str = new String( sql_str.getBytes("gb2312"), "ISO-8859-1" );

 


如果数据库系统支持Unicode,那么请尽量采用Unicode。有些手册上建议你根据具体情况决定是否使用Unicode,因为Unicode将占用更多的存储空间,而且如果采用UTF-8,排序的速度将会"减慢30% (mysql)",请不要为这些词语而顾虑,大多数情况这些都不是问题。

 

对于SQL Server 2000,这篇文章值得一读:

 

 http://www.microsoft.com/china/msdn/library/techart/IntlFeaturesInSQLServer2000.asp

 

最关键的就是你需要在字符串左边加上N字符(N一定要大写),如

 

 INSERT INTO table(name_en, name_native) VALUES('yokohama', N' 横浜 ')

 


对于Sybase数据库(Sybase 11.5, Sybase 12),系统不支持UTF-16,但支持UTF-8,为了使用Unicode,你可能需要下面的连接字串:
 jdbc:sybase:Tds:127.0.0.1:4000/database?charset=utf8&jconnect_version=0

 

类似的,在SQL语句中使用字符N修饰的字串,使SQL分析器认为字串是Unicode编码的。

 

对于MySQL数据库,系统支持四个级别的字符集设置:
  连接,数据库,表,字段
MySQL参考手册第9章有详细的讨论,但注意版本要求4.1.0以上,同时Windows (nt,2k,xp) 的用户请注意 4.1.0 有个bug,你必须使用4.1.1才能正确使用Unicode。

 

在 SQL Server 和 Sybase 中都有N开头的字段类型,它们被设计用于国际化的字符存储。在SQL Server中,比如NTEXT实际上就是用Unicode存储的的字段类型。

 

SQL-99规定了Unicode字符串统一使用 u 前缀,如 u"コンピュータ",但目前还没有见哪个数据库系统支持这种语法。

 


附:几个字符集支持的测试例子 (需要测试用的源码可以向我要:jljljjl@yahoo.com

 

声明:
  Connection c; 
  Statement s;

 

生成数据:
  String lit1 = "的文本:中华人民共和国]"; 
  String[] encs = new String[] {
   "(default)",    
   "ISO-8859-1", 
   "cp850", 
   "gb2312", 
   "gbk", 
   "big5", 
   "UTF-16LE", 
   "UTF-16BE", 
   "UTF-8", 
  }; 
  
  String javaSrc = "[这是默认编码" + lit1; 
  byte[] rawdata; 
  
  s.executeUpdate("DELETE FROM StringTable"); 
  for (int i = 0; i < encs.length; i++) {
   String targetEncoding = encs[i]; 
   javaSrc = "[这是" + targetEncoding + lit1; 
   String testTarget; 
   
   if (i == 0) {
    rawdata = javaSrc.getBytes(); 
    testTarget = new String(rawdata); 
   } else {
    rawdata = javaSrc.getBytes(targetEncoding); 
    testTarget = new String(rawdata); 
   } 
   
   System.out.println(testTarget); 
   
   String sql = ("INSERT INTO StringTable(charset,text) VALUES(" +  
    "'" + targetEncoding + "', N'" + testTarget + "')"); 
   System.out.println(sql); 
   
   s.executeUpdate(sql); 
  }

 

获取数据:
  ResultSet rs = s.executeQuery("SELECT * FROM StringTable"); 
  
  String charset; 
  String text; 
  while (rs.next()) {
   charset = rs.getString("charset").trim(); 
   text = rs.getString("text"); 
   
   System.out.println(charset + ": [" + text + "]"); 
   
   byte[] raws = text.getBytes(); 
   
   String restore; 
   if ("(default)".equals(charset)) {
    restore = new String(raws); 
   } else {
    restore = new String(raws, charset); 
   }
   System.out.println("   --> [" + restore + "]"); 
  }

 

 

 

典型测试结果:
SQL-Server, type = ntext

 

(default): [[这是(default)的文本:中华人民共和国]]
   --> [[这是(default)的文本:中华人民共和国]]
ISO-8859-1: [[??ISO-8859-1???????????]]
   --> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
   --> [[??cp850???????????]]
gb2312: [[这是gb2312的文本:中华人民共和国]]
   --> [[这是gb2312的文本:中华人民共和国]]
gbk: [[这是gbk的文本:中华人民共和国]]
   --> [[这是gbk的文本:中华人民共和国]]
big5: [[?琌big5ゅセい?チ㎝?]]
   --> [[?是big5的文本:中?人民共和?]]
UTF-8: [[杩欐槸UTF-8鐨勬枃鏈細涓崕浜烘皯鍏卞拰鍥絔]
   --> [[这是UTF-8的文本:中华人民共和国]]

 

 

 


SQL-Server, type = text

 

(default): [[这是(default)的文本:中华人民共和国]]
   --> [[这是(default)的文本:中华人民共和国]]
ISO-8859-1: [[??ISO-8859-1???????????]]
   --> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
   --> [[??cp850???????????]]
gb2312: [[这是gb2312的文本:中华人民共和国]]
   --> [[这是gb2312的文本:中华人民共和国]]
gbk: [[这是gbk的文本:中华人民共和国]]
   --> [[这是gbk的文本:中华人民共和国]]
big5: [[?琌big5ゅセい?チ㎝?]]
   --> [[?是big5的文本:中?三民囝和?]]
UTF-8: [[杩欐槸UTF-8鐨勬枃鏈細涓崕浜烘皯鍏卞拰鍥絔]
   --> [[这是UTF-8的文本:中华人民共和国]]

 

 

 

 

 

Sybase, type = char
(default): [[??(default)???????????]]
   --> [[??(default)???????????]]
ISO-8859-1: [[??ISO-8859-1???????????]]
   --> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
   --> [[??cp850???????????]]
gb2312: [[??gb2312???????????]]
   --> [[??gb2312???????????]]
gbk: [[??gbk???????????]]
   --> [[??gbk???????????]]
big5: [[??big5???????????]]
   --> [[??big5???????????]]
UTF-16LE
   --> [[?啦吀??????????乎?民共?]]
UTF-16BE: 
   --> [[??唀吀??????????乎?共吿??]

 

UTF-8: [[???UTF-8?????????????????]
   --> [[???UTF-8?????????????????]

 


Sybase, type = nchar
(default): [[??(default)???????????]]
   --> [[??(default)???????????]]
ISO-8859-1: [[??ISO-8859-1???????????]]
   --> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
   --> [[??cp850???????????]]
gb2312: [[??gb2312???????????]]
   --> [[??gb2312???????????]]
gbk: [[??gbk???????????]]
   --> [[??gbk???????????]]
big5: [[??big5???????????]]
   --> [[??big5???????????]]
UTF-16LE
   --> [[?啦吀??????????乎?民共?]]
UTF-16BE: 
   --> [[??唀吀??????????乎?共吿??]

 

UTF-8: [[???UTF-8?????????????????]
   --> [[???UTF-8?????????????????]

 

 

 

Sybase, type = char, charset=utf8
(default): [[这是(default)的文本:中华人民共和国]]
   --> [[这是(default)的文本:中华人民共和国]]
ISO-8859-1: [[??ISO-8859-1???????????]]
   --> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
   --> [[??cp850???????????]]
gb2312: [[这是gb2312的文本:中华人民共和国]]
   --> [[这是gb2312的文本:中华人民共和国]]
gbk: [[这是gbk的文本:中华人民共和国]]
   --> [[这是gbk的文本:中华人民共和国]]
big5: [[?琌big5ゅセい?チ㎝?]]
   --> [[?是big5的文本:中?人民共和?]]
UTF-16LE:  [[这是UTF-16LE的文本?中华人民共和国]]
UTF-16BE:  [[这是UTF-16BE的文本?中华人民共和嘿]]

 

UTF-8: [[杩欐槸UTF-8鐨勬枃鏈細涓崕浜烘皯鍏卞拰鍥絔]
   --> [[这是UTF-8的文本:中华人民共和国]]

 

 

 


Sybase, type = nchar, charset=utf8

 

(default): [[这是(default)的文本:中华人民共和国]]
   --> [[这是(default)的文本:中华人民共和国]]
ISO-8859-1: [[??ISO-8859-1???????????]]
   --> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
   --> [[??cp850???????????]]
gb2312: [[这是gb2312的文本:中华人民共和国]]
   --> [[这是gb2312的文本:中华人民共和国]]
gbk: [[这是gbk的文本:中华人民共和国]]
   --> [[这是gbk的文本:中华人民共和国]]
big5: [[?琌big5ゅセい?チ㎝?]]
   --> [[?是big5的文本:中?人民共和?]]
UTF-16LE:  --> [[这是UTF-16LE的文本?中华人民共和国]]
UTF-16BE:  --> [[这是UTF-16BE的文本?中华人民共和嘿]]
UTF-8: [[杩欐槸UTF-8鐨勬枃鏈細涓崕浜烘皯鍏卞拰鍥絔]
   --> [[这是UTF-8的文本:中华人民共和国]]

 

 

 

 

 

Sybase, type = char, charset=cp936
(default): [[这是(default)的文本:中华人民共和国]]
   --> [[这是(default)的文本:中华人民共和国]]
ISO-8859-1: [[??ISO-8859-1???????????]]
   --> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
   --> [[??cp850???????????]]
gb2312: [[这是gb2312的文本:中华人民共和国]]
   --> [[这是gb2312的文本:中华人民共和国]]
gbk: [[这是gbk的文本:中华人民共和国]]
   --> [[这是gbk的文本:中华人民共和国]]
big5: [[?琌big5ゅセい?チ㎝?]]
   --> [[?是big5的文本:中?人民共和?]]
UTF-16LE: --> [[这是UTF-16LE的文本?中华人民共和国]]
UTF-16BE: --> [[这是UTF-16BE的文本?中华人民共和嘿]]
UTF-8: [[杩欐槸UTF-8鐨勬枃鏈細涓崕浜烘皯鍏卞拰鍥絔]
   --> [[这是UTF-8的文本:中华人民共和国]]

 

 

 

Sybase, type = char, charset=eucgb
(default): [[这是(default)的文本:中华人民共和国]]
   --> [[这是(default)的文本:中华人民共和国]]
ISO-8859-1: [[??ISO-8859-1???????????]]
   --> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
   --> [[??cp850???????????]]
gb2312: [[这是gb2312的文本:中华人民共和国]]
   --> [[这是gb2312的文本:中华人民共和国]]
gbk: [[这是gbk的文本:中华人民共和国]]
   --> [[这是gbk的文本:中华人民共和国]]
big5: [[??big5?ゅセ?い??チ???]]
   --> [[??big5?文本?中??民???]]
UTF-16LE: --> [[?啦吀??????????乎?民共?]]
UTF-16BE: --> [[??唀吀??????????乎?共吿??]
UTF-8: [[杩??UTF-8??????涓??浜烘??卞???]
   --> [[???UTF-8?????????人????????]

 

 

 


Sybase, type = nchar, charset=eucgb

 

(default): [[这是(default)的文本:中华人民共和国]]
   --> [[这是(default)的文本:中华人民共和国]]
ISO-8859-1: [[??ISO-8859-1???????????]]
   --> [[??ISO-8859-1???????????]]
cp850: [[??cp850???????????]]
   --> [[??cp850???????????]]
gb2312: [[这是gb2312的文本:中华人民共和国]]
   --> [[这是gb2312的文本:中华人民共和国]]
gbk: [[这是gbk的文本:中华人民共和国]]
   --> [[这是gbk的文本:中华人民共和国]]
big5: [[??big5?ゅセ?い??チ???]]
   --> [[??big5?文本?中??民???]]
UTF-16LE: --> [[?啦吀??????????乎?民共?]]
UTF-16BE: --> [[??唀吀??????????乎?共吿??]
UTF-8: [[杩??UTF-8??????涓??浜烘??卞???]
   --> [[???UTF-8?????????人????????]

 

 

 


(从以上测试中可以看出,我的.java文件是用gb2312编码的。)

分享到:
评论

相关推荐

    jdbc连接oracle字符集不同出现乱码

    这种情况通常发生在远程 Oracle 数据库与本地 Oracle 数据库的字符集设置不一致的情况下。 在本案例中,远程 Oracle 数据库使用的字符集为 `AMERICAN_AMERICA.US7ASCII`,而本地 Oracle 数据库使用的字符集为 `...

    jdbc问题集收藏总结

    ### JDBC问题集锦与解决方案 #### 一、ResultSet的理解与使用 **问题描述:** 在使用JDBC过程中,经常需要处理查询结果集`ResultSet`。`ResultSet`对象表示执行SQL语句后返回的结果集,它提供了对结果集中数据的...

    JDBC知识点总结

    ### JDBC知识点总结 #### 一、JDBC概述 **简介** JDBC (Java Database Connectivity) 是由 SUN 公司提供的一套标准规范,用于在 Java 应用程序中访问关系型数据库。它允许 Java 程序通过统一的 API 与不同的...

    Web下Java语言如何访问不同字符集的Oracle数据.pdf

    总结起来,Java在Web环境下访问不同字符集的Oracle数据时,需要理解并处理Java和Oracle字符集的差异,通过设置JVM、数据库连接参数以及编码/解码操作来确保数据的一致性和准确性。同时,开发者应该熟悉Oracle的NLS...

    JDBC学习笔记总结,可以看看

    "JDBC学习笔记总结" JDBC(Java Database Connectivity)是一种Java API,用于连接和操作关系数据库。下面是JDBC学习笔记的总结: 连接到数据库的方法 1. ODBC(Open Database Connectivity):是一个以C语言为...

    jdbcoracle(多国语言支持)

    《JDBC与Oracle的多国语言...总结,JDBC与Oracle的多国语言支持是一个复杂但至关重要的任务,涉及数据库配置、SQL语句编写、字符集转换等多个环节。理解并掌握这些知识,将有助于开发出适应全球市场的高质量软件系统。

    Java字符集[定义].pdf

    Java连接数据库时,如JDBC,需配置数据库连接的字符集,例如MySQL的`useUnicode=true&characterEncoding=utf8`。不匹配的字符集可能导致数据存储或检索时出现乱码。 4. Java的CharSet类 Java的`java.nio.charset....

    JDBC连接各种数据库总结

    **JDBC连接各种数据库总结** Java Database Connectivity (JDBC) 是Java编程语言中用于与数据库交互的一组标准接口和类。它允许Java开发者执行SQL语句并处理返回的结果。本篇文章将详细介绍如何使用JDBC连接不同...

    JDBC连接数据库经验总结

    通过JDBC,开发者可以执行SQL语句并处理结果集,从而实现了数据库的增删改查操作。JDBC的关键组件包括: 1. **DriverManager**:负责加载驱动并创建与数据库的连接。 2. **Connection**:表示与数据库的一个连接。 ...

    JDBC连接orcal,sql_server_,mysql_数据库字符串资料总结

    - **字符集设置**: 如果需要指定字符集,可以在URL后面加上`?useUnicode=true&characterEncoding=utf8`。 #### 五、其他数据库连接示例 除了上述提到的Oracle、SQL Server和MySQL之外,还有很多其他的数据库管理...

    MySQL + JDBC彻底解决中文乱码问题

    在 Java 应用程序中使用 JDBC 连接 MySQL 数据库时,需要确保连接 URL 中包含了正确的字符集参数。示例 URL 如下: ```java String url = "jdbc:mysql://localhost:3306/server?useUnicode=true&characterEncoding=...

    sqljdbc42 jdbc for java

    2. 支持Unicode:完全支持Unicode字符集,使得国际化和本地化应用开发更为便捷。 3. 批处理:允许一次性提交多个SQL语句,提高批量操作的性能。 4. 游标支持:提供多种游标类型,使开发者可以选择不同的数据读取模式...

    SSH+mysql开发字符集问题

    下面将详细介绍与字符集相关的几个核心概念: - **character_set_client**: 客户端使用的字符集。 - **character_set_connection**: 连接级别的字符集,用于确定客户端发送到服务器的数据所使用的字符集。 - **...

    Java解决WE8DEC字符集乱码问题

    总结来说,解决Java中的WE8DEC字符集乱码问题涉及多个层面,从文件读写、数据库交互到Web请求和数据交换,都需要正确设置和处理字符编码。理解这些环节并应用适当的编码策略,是确保程序正确处理各种字符集的关键。

    关于Universe和IDT链接数据库的JDBC配置

    1. **字符集问题**: 如果仍然遇到字符集转换失败的问题,检查是否已正确设置了环境变量,以及JDBC驱动文件是否完整无误。 2. **连接失败**: 检查JDBC驱动文件的版本是否与Oracle客户端版本匹配;同时确认数据库URL、...

    jdbc学习笔记(PDF格式)

    JDBC提供了与数据库建立连接、发送SQL语句并处理结果的基本功能。 1. **JDBC的角色与协议** - **角色**:JDBC作为一套协议,是Java开发者与数据库厂商之间的一种约定。 - **协议内容**:Sun公司(现在为Oracle...

    java中jdbc的总结

    总结,Java的JDBC提供了强大的数据库操作能力,通过理解其核心机制和最佳实践,能有效提升Java应用程序与数据库的交互效率和数据管理的可靠性。在实际开发中,结合连接池、事务管理和异常处理,能够构建健壮的数据库...

    使用JDBC总结操作数据库

    总的来说,JDBC是Java与数据库交互的基础,理解并熟练掌握JDBC的使用,能够帮助开发者更高效地进行数据库操作。在实际开发中,通常会结合使用`PreparedStatement`和工具类如`QueryRunner`,以提高代码的可读性和安全...

    jdbc连接数据库的乱码问题(已解决)

    jdbc连接mysql出现了乱码,总结起来就是里面的四个编码方式是一样的时候,就不会乱码了,简之,客户连接数据库返回结果(编码必须一致)。

Global site tag (gtag.js) - Google Analytics