• c#+mysql 中文乱码


    c#+mysql 中文乱码

    遇到一个奇怪的问题,C#读取mysql中文正常,写入时发生乱码

    网上查阅原因,发现如下信息

    ---------------------------------------------------------------------

    一、错误读出

    现象:一个已经存在数据的MySQL数据库,该数据库的数据用系统中其它软件、网页查看均正常,使用MySQLcc之类的客户端查看也正常,可是在新写的网页中总是显示乱码。

    分析:其它系统都可以正常查看数据,说明数据本身是没有问题的。在网页中显示乱码,一定是网页的编码字符集和获取到的数据的编码字符集不一至。比如数据库的字符集是UTF8的,而网页的字符集是gb2312的,那么网页就会把UTF8编码的字体串当作gb2312的来处理,结果产生乱码。

    解决办法:在连接数据库时,设定连接字符集,使连接字符集和当前网页或客户端程序使用的字符集一致。可以使用MySQL的Set Names指令设定连接字符集。假设网页的字体集为gb2312。在连接MySQL后,在连接上执行如下SQL语句:

    Set Names ‘gb2312’

    在以后所有这个连接上的查询,MySQL都会自动把数据库中的数据转换成gb2312编码格式传过来。

    二、错误写入

    现象:一个网页或程序向一个MySQL数据库中写数据,写完后,这个网页或程序自己可以正常读取数据,而从其它客户端或网页中读取数据都是乱码。

    分析:其它的正常的客户端出现乱码,说明数据库中的字符编码不对。写数据的那个网页能正常读取,是因为写和读都用了错误的编码格式,将错就错,反而能读出正确的数据了。比如数据库中设定的字符集为UTF8,而网页使用gb2312编码执行了插入数据的SQL,那么MySQL就会把这些gb2312的编码当成是UTF8的编码写进数据库。当其它客户端访问数据时,会按系统的设定,以UTF8 格式读取数据,而数据其实是使用gb2312编码的,结果就出现了乱码。只有写数据的那个网页会把这些数据当成gb2312的,也只有那个网页能正常显示数据。

    解决办法:同第一条,即:使用Set Names指令设定连接字符集。

    在设定了连接字符体的连接上执行数据操作,所有的数据都将被MySQL自动、正确地转换为数据库中设定的编码格式保存。

    通过以上两点,我们可以看到,只要在连接MySQL时,正确地设定了字符集,无论数据库本身是使用什么格式编码的,都能得到正确的结果。也许有人会以为写数据时设定的字符集必需和读数据时一致,事实上完全没有必要。程序所要做的只是告诉 MySQL,目前操作MySQL使用的是什么字符集即可。因为MySQL会自动完成如下的转换工作:

    写数据库时用的字符集-->存诸数据的字符集-->读取数据的字符集。

    笔者以为MySQL对多语言字符集的处理是非常优秀的,并且每次建立到MySQL的连接都会立刻使用Set Names设定字符集,然而最近还是出现了一回乱码,如下面所述。

    三、无知的程序包

    现象:使用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#中字符默认编码为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();   

    期待已久的中文终于顺利写入了!

  • 相关阅读:
    spring boot 配置示例
    MyBatis 常用标签用法
    http请求头部常用参数
    CentOS7使用firewalld打开关闭防火墙与端口
    java8 base64
    MD5工具类
    各种远程登录工具
    MySql 常用命令
    spring-boot-mybaits 开启事务
    springboot 项目打包到 linux下无法 运行
  • 原文地址:https://www.cnblogs.com/hailexuexi/p/3457426.html
Copyright © 2020-2023  润新知