关于C#ASP.net)存取MySQL LongText字段的心得

 

1.LongText字段是MySQL用于存储超长字符串的数据库类型,有点类似MSSQL的memo。

 

2.Connector/NET读取LongText的内部实现过程:

1)  Connector/NET内部将LongText看作字符串,对外以字符串的方式进行读写,不运行调用getBytes的方法。

2)根据MySQL的配置信息,获得MySQL的字符集,并根据字符集信息生成System.Text.Encode对象

3)以byte[]的方式从MySQL数据库里将LongText字段信息读取出

4)使用System.Text.Encode的GetString方法对字符串进行解码,并返回给用户

 

3.Connector/NET写LongText的内部实现(猜测,没有看过代码)

1)根据MySQL的配置信息,获得MySQL的字符集,并根据字符集信息生成System.Text.Encode对象

2)  System.Text.Encode对象的GetBytes方法对字符串进行编码,转换为byte[]

3)将byte[]以二进制流的方式写入数据库对应的LongText字段

 

4.Connector/NET对MySQL数据库默认的字符集

1)  MySQL 4.1以前的版本(这里特指MySQL 4.0),如果字符集是latin1(拉丁文),则.net 内部的System.Text.Encode对象为Latin1Encoding(.net内部私有对象)。CodePage=28591(EncodingName = Western European (ISO))

2)  MySQL 4.1 的版本,如果字符集是latin1,则内部的System.Text.Encode对象为CodePageEncoding。CodePage=1252(EncodingName = Western European (Windows))

3)如果是MySQL的字符集定义为GB2312,或者UTF8(MySQL 4.0不支持),.net内部的编码方式则会根据MySQL的字符集确定。

 

5.Connector/NET读取MySQL的LongText字段时产生乱码的原因

       Connector/NET内部将LongText字段看作字符串,而LongText字段在存取得时候,内部是按照byte[]方式进行处理的,因此,在存储LongText字段的时候,需要对传入的LongText支点的字符串(.net字符串,其内部采用unicode方式编码)进行编码,并将得到的byte[]存储到数据库里。相反,读取LongText字段的时候,需要将从数据库里读出的byte[]进行解码,还原为.net字符串。

       在这个编码/解码的过程中,需要指定byte[]的编码类型(字符集类型)。字符集类型可以从MySQL获得。MySQL在安装的时候,将字符集默认为latin1。(MSSQL则会在安装的时候检查操作系统的字符集设置,并将字符集设置与当前操作系统一致)因此Connector/NET组件在存取LongText字段的时候,就会将字符串按照latin1字符集的方式进行处理,凡是出现中文的地方,都会因为字符集编码不一致,而用错误的字符串替换。而如果MySQL被其它程序按照当前用户字符集方式编码(中文的GB2312)写入,在MySQL读取的时候,也就会出现解码错误,得到乱码。

       总之一句话,因为MySQL的字符集设置错误就会造成Connector/NET存取的时候出现乱码。

 

6.如何从MySQL 4.0数据库读取LongText信息(非MySQL定义字符集信息)

 

       这里假设原来存储到MySQL数据的时候是按照GB2312方式存储,并且当前系统默认得字符集也是GB2312,MySQL的字符集未修改为latin1。

   

byte[] buf = new byte[1024 * 10];

     //   向按照错误的字符集读取字符串

     string s= dr.GetString(0);

     //   按照错误的字符集,将字符串还原为byte数组

     System.Text.Encoding.GetEncoding(28591).GetBytes(s, 0, s.Length, buf, 0);

     //   重新按照正确的字符集生成字符串

     s=System.Text.Encoding.Default.GetString(buf);

 

 

7.如何种MySQL 4.1数据库读取LongText信息(非MySQL定义字符集信息)

       代码和上面的一样,所不同的只是将28591替换为1252

 

8.如何将字符串写入LongText里(非MySQL定义字符集信息)

       首先,如果通过以往的写字符方法写数据库的话,字符串里非英文字符会因为错误的编码(默认的latin1)而丢失(如果MySQL的字符集是GB2312或者UTF8则不会出现该问题),这样无论后面我们如何正确的解码,都不可能得到正确的字符串。所以,如果要写入非英文字符的字符串,就不能走正常的路线,而需要把LongText看作二进制字段,以bit流方式写入。写入方式和blob字段写入方式一样,详细方法参考bruse的文章。

     

MySql.Data.MySqlClient.MySqlCommand cmm = null;

     cmm = new MySql.Data.MySqlClient.MySqlCommand("insert into test(name) values(?name)", connect);

     //   以将该字段看作二进制流

     MySql.Data.MySqlClient.MySqlParameter param = null;

     param = new MySql.Data.MySqlClient.MySqlParameter("?name", System.Data.DbType.Binary);

     //   对输入的字符串使用GB2312进行编码

     param.Value = System.Text.Encoding.Default.GetBytes("aa中文测试");

     cmm.Parameters.Add(param);

cmm.ExecuteNonQuery();

  

 

9.以UTF-8、UTF16(Unicode)、BigUnicode的方式将字符串写入LongText里

       基本方法同“7.如何将字符串写入LongText”,不同之处在于编码方式由Default改为UTF8、Unicode、BigUnicode。

 

 

10.如何兼容MySQL 4.0、4.1的读取方法(读取UTF-16)

       读取LongText的关键在于如何将LongText得到的字符串解码为byte数组,并重新编码。而Connector/NET控件在两个MySQL版本之间,对默认的编码采用了两种不同的编码/解码方式,从而导致乱码,解决的方案有:

1)修改Connector/NET控件,提供一个获得当前Connector/NET控件(MySQL)的字符集的方法。

2)修改Connector/NET控件,对MySQL所有版本的默认字符集都采用统一的解码方式,即如果字符集为latin1将统一采用CodePage=28591或者CodePage=1252的方式进行解码。(缺点:如果MySQL的字符集改变,则读取代码在创建System.Text.Encode对象也需要改变)

3)修改应用程序,针对2个不同版本的MySQL数据库采用2套解决方案(缺点同2。而且需要修改的地方更多)。

4)在MySQL连接字符串里确定字符集(在连接字符串里添加charset=gb2312),并修改程序,按照gb2312的方式还原编码(推荐使用)

 

 

p.s.

1.Connector/NET是一个.net访问MySQL的组件,本文使用的版本是1.0.0.7,MySQL使用的版本是4.0 和 4.1。.net版本1.1

 

       2.本文针对LongText采用如此特殊的字符集编码转换过程,是因为其它应用往MySQL数据库里写数据的时候是按照UTF-16(Unicode或BigUnicode)进行编码的,MySQL4.0和4.1都不直接支持UTF-16的字符集。

 

       3.如果只有一个应用访问MySQL数据库,可直接将MySQL的字符集改为GB2312或者UTF-8,不需按照本文这种婉转的编码方式进行字符集转换。