遇到一个奇怪的问题,C#读取mysql中文正常,写入时发生乱码mysql
网上查阅缘由,发现以下信息web
---------------------------------------------------------------------sql
1、错误读出
现象:一个已经存在数据的MySQL数据库,该数据库的数据用系统中其它软件、网页查看均正常,使用MySQLcc之类的客户端查看也正常,但是在新写的网页中老是显示乱码。
分析:其它系统均可以正常查看数据,说明数据自己是没有问题的。在网页中显示乱码,必定是网页的编码字符集和获取到的数据的编码字符集不一至。好比数据库的字符集是UTF8的,而网页的字符集是gb2312的,那么网页就会把UTF8编码的字体串看成gb2312的来处理,结果产生乱码。
解决办法:在链接数据库时,设定链接字符集,使链接字符集和当前网页或客户端程序使用的字符集一致。可使用MySQL的Set Names指令设定链接字符集。假设网页的字体集为gb2312。在链接MySQL后,在链接上执行以下SQL语句:
Set Names ‘gb2312’
在之后全部这个链接上的查询,MySQL都会自动把数据库中的数据转换成gb2312编码格式传过来。
2、错误写入
现象:一个网页或程序向一个MySQL数据库中写数据,写完后,这个网页或程序本身能够正常读取数据,而从其它客户端或网页中读取数据都是乱码。
分析:其它的正常的客户端出现乱码,说明数据库中的字符编码不对。写数据的那个网页能正常读取,是由于写和读都用了错误的编码格式,将错就错,反而能读出正确的数据了。好比数据库中设定的字符集为UTF8,而网页使用gb2312编码执行了插入数据的SQL,那么MySQL就会把这些gb2312的编码当成是UTF8的编码写进数据库。当其它客户端访问数据时,会按系统的设定,以UTF8 格式读取数据,而数据实际上是使用gb2312编码的,结果就出现了乱码。只有写数据的那个网页会把这些数据当成gb2312的,也只有那个网页能正常显示数据。
解决办法:同第一条,即:使用Set Names指令设定链接字符集。
在设定了链接字符体的链接上执行数据操做,全部的数据都将被MySQL自动、正确地转换为数据库中设定的编码格式保存。
经过以上两点,咱们能够看到,只要在链接MySQL时,正确地设定了字符集,不管数据库自己是使用什么格式编码的,都能获得正确的结果。也许有人会觉得写数据时设定的字符集必需和读数据时一致,事实上彻底没有必要。程序所要作的只是告诉 MySQL,目前操做MySQL使用的是什么字符集便可。由于MySQL会自动完成以下的转换工做:
写数据库时用的字符集-->存诸数据的字符集-->读取数据的字符集。
笔者觉得MySQL对多语言字符集的处理是很是优秀的,而且每次创建到MySQL的链接都会马上使用Set Names设定字符集,然而最近仍是出现了一回乱码,以下面所述。
3、无知的程序包
现象:使用C#编程,使用MySQL提供的链接程序库包访问数据库,使用 MySqlConnection类链接数据库,链接以后马上调用Set Names设定链接字符串,而后使用MySqlCommand类执行SQL,并使用MySqlDataReader读取数查询结果。然而,当我调用 MySqlDataReader的成员方法GetString获取数据的时候,发现获得的全是乱码。百思不得其解。
分析:经仔细检查,确信问题没有出在MySQL链接上面,这时我想到了C#中对 string类型的处理。在C#中字符串和C/C++中有很大不一样。在C/C++中一个字符就是一个字节,而在C#中,按不一样的编码格式,一个字符也能够是多个字节的。好比”啊”就是一个字符,若是一个字符串s=”啊”; 那么s的Length属性为1,而不是C/C++中的2。我想MySQL程序包也许并不知道链接上传过来的字符是什么编码的,它由于无知,因此只是按单字节字符把这些数据组织成一个string,这个生成的string就是我获得的乱码。事实上也的确是这样。
解决办法:把这些数据从新组织起来,而后使用正确的编码方法从新生成string。C#中System.Text包内的Encoding类提供了字符集的编/解码方法。
1)首先仍是设定链接字符集,以确认收到的字符的编码方式。
2)把GetString获得的字符串转换到byte数组中。
3)使用Systec.Text.Encoding包中相应字符集的解码方法GetString获得新的字符串。
为了通用性,咱们使用System.Text.Encoding的默认字符集。链接数据库时,设置数据库链接字符集使用的SQL指令strSetCharset为以下值:
string strSetCharset = “Set Names ” + System. Text. Encoding .Default. HeaderName;
在获取数据时,使用下面的函数获得真正的字符串:
private string DBStringToNormal(string dbStr)
{
byte[] str = new byte[dbStr.Length];
for (int i = 0; i < dbStr.Length; ++i)
str[i] = (byte)(dbStr[i]);
return System.Text.Encoding.Default.GetString(str, 0, dbStr.Length);
}
-----------------------------------------------------------------------------------------------------------------数据库
看到这个文章受到启发,重要的一句是:编程
经过以上两点,咱们能够看到,只要在链接MySQL时,正确地设定了字符集,不管数据库自己是使用什么格式编码的,都能获得正确的结果。也许有人会觉得写数据时设定的字符集必需和读数据时一致,事实上彻底没有必要。程序所要作的只是告诉 MySQL,目前操做MySQL使用的是什么字符集便可。由于MySQL会自动完成以下的转换工做:
写数据库时用的字符集-->存诸数据的字符集-->读取数据的字符集。c#
由此想个人问题多是写入时声明的个人字符编码与我实际的不符,C#中字符默认编码为GB2312,因而程序改动以下:数组
1:在连接字符加入字符编码声明函数
<add key="mysqlconstr" value="UserId=root;Allow Zero Datetime=true;Charset=gb2312;Host=125.*.*.*;Database=dbname;Password=123456"/>字体
向mysql说明个人字符编码是gb2312, 不要搞错编码
2:在数据库类中每一插入数据语句前加入编码声明
cmd = new MySqlCommand("set names gb2312;"+sql,conn);
cmd.ExecuteNonQuery();
期待已久的中文终于顺利写入了!