我有一个文件,内有一些数据,该文件是用GB18030编码的。我用下面的代码可以读写:
    is = new FileInputStream(f);
    InputStreamReader isr = new InputStreamReader(is, "GB18030");
    BufferedReader br = new BufferedReader(isr);
    String s = br.readLine();此时s中以ucs方式存放。使用System.out.println(s)可以正确地打印该行数据。接下来将其存入数据库,使用:
PreparedStatement ps;
try {
    ps = con.prepareStatement("insert into clusterdb.stockinfo (StockCode, StockName) values(?, ?)");
    ps.setString(1, stockInfos[0]);
    ps.setBytes(2, stockInfos[1].getBytes("GB18030"));    ps.execute();
    ps.close();
}
这样能正确地将数据存入mysql,并且读出。读出时无须做任何转换,可以直接用System.out.println(s)打印StockName(含中文字符).数据库设置为utf-8编码。上述语句中,如果将getBytes("GB18030")改为getBytes("utf-8"),则会出现乱码。请问原因为何?既然数据库已设置为utf-8编码,那么不应该将SQL语句填充为 utf-8 再存放吗?为什么转换成GB18030反倒能成功呢?

解决方案 »

  1.   

    SQL 语句里出现的字符串应该是什么编码,并不取决于“数据库本身的编码方式”,而是取决于“数据库连接的编码方式”。根据你描述的情况,大概你的数据库连接是 GBK 编码的,具体说,就是在你那个 SQL 语句之前执行了 SET NAMES GBK 语句(如果不是显式执行的,那就是缺省为 GBK)。如果你希望 SQL 语句使用 UTF-8 编码,可以先执行一个 SET NAMES UTF-8
    ■□■□■□■□■□■□■□■
    □             □
    ■  忍以明志 勤以致远  ■
    □             □
    ■□■□■□■□■□■□■□■
    基于CSDN论坛提供的插件扩展功能,自己做了个签名档工具,分享给大家,欢迎技术交流 :)
      

  2.   

    下面一张草图,供参考。其中红色的连线,就是 SET NAMES 设置的编码。客户端程序 ------------> 客户端接口 ----------> 服务端接口 --------------> 数据库存储
      UCS2       转换成GBK                GBK传输                转换成UTF-8     UTF-8客户端程序 <------------ 客户端接口 <---------- 服务端接口 <------------ 数据库存储
      UCS2       转换成UCS2                GBK传输                转换成GBK     UTF-8
      

  3.   

    客户端程序 ------------> 客户端接口 ----------> 服务端接口 --------------> 数据库存储
     UCS2   转换成GBK        GBK传输        转换成UTF-8   UTF-8客户端程序 <------------ 客户端接口 <---------- 服务端接口 <------------ 数据库存储
     UCS2   转换成UCS2        GBK传输        转换成GBK   UTF-8
      

  4.   

    谢谢Maquan!问题已经解决了。原因是我使用的Mysql数据库,它总共可以在三个层级上设置数据的编码方式:数据库级、表级和字段级。我在建库和建表时未指定UTF-8,后来通过更改数据库的schema将其改为UTF-8 default colation,已为全数据库都是utf-8的了,但其实先前已建的表和其字段的coloation属性已定下来了,不会跟着变。回顾一下:
    1. MySql可以在三个层级上设置文本数据的编码方式:数据库级、表级和字段级。作用域越小的,效力越高。
    2. 连接字符串应该设置跟数据库一致的编码方式:
        String url = "jdbc:mysql://localhost:5000/clusterdb?characterEncoding=utf-8";
       问题:如果数据库使用的编码方式并不一致,比如数据库级为utf-8,某张表的某个字段使用了GB18030,结果如何?
    3. 从InputStream读取数据到String变量时,应该指定正确的源数据的编码方式。String总是以UCS2的方式编码。
    4. 使用PreparedStatement以及PreparedStatement.setString来插入数据。setString会自动进行编码的转换,也可以使用PreparedStatement.setBytes(x, String.getBytes("utf-8"))来插入数据。
    5. String.getBytes()函数接受一个参数,这个参数即为生成数据的编码方式。例如:String.getBytes("utf-8"),则会生成一个带utf BOM(EF BB BF).
      

  5.   


    这个问题,往往是我们把它想复杂了,其实很简单,那就是:MySQL 会处理好一切。我们要做的,就是两件事:1. 在建立连接的时候告诉 MySQL “我们的 SQL 语句将要使用什么编码方式”;2. 然后,在发送 SQL 语句的时候确实“使用前面声明的编码方式”,就 OK 了。无论你的数据库、表、字段设置的是什么编码方式,MySQL 都会处理得很好,定义它们的时候,完全不必考虑“乱码”问题,需要考虑的是两点:1. 指定的编码方式确实能兼容将要保存的数据,比如,如果预期将在一个字段中同时存储简体、繁体、日文、韩文,那么,UTF-8几乎是唯一的选择;2. 在满足前一条的前提下,尽量提高存储效率,以及减少传输过程中的编码转换环节。综上,一般来说,UTF-8 是最好、最简单的选择,只是存储效率略逊。如果你能肯定“只需要简体中文”,那么 GBK 也是个不错的选择。■□■□■□■□■□■□■□■
    □             □
    ■  忍以明志 勤以致远  ■
    □             □
    ■□■□■□■□■□■□■□■
    基于CSDN论坛提供的插件扩展功能,自己做了个签名档工具,分享给大家,欢迎技术交流 :)