现在的位置: 首页 > 综合 > 正文

GB2312,GBK,Unicode

2012年10月20日 ⁄ 综合 ⁄ 共 4981字 ⁄ 字号 评论关闭

 

           为了使我们的计算机能够显示文字或字符,首先要内存中可以存储文字或字符。要存储一个文字或者字符有多种方式:

           (1)我们可以把文字变为图片(点阵),直接保存起来,当需要显示的时候,把图片绘制出来。

           (2)把文字或者字符变成矢量数据存储起来,需要显示的时候,再根据矢量规则绘制出来即可。

           (3)把文字或者或者先编号,然后要问题显示样式与编号一一对应起来,当需要显示文字的时候,首先根据编号去找文字对应的图片,然后绘制。

 

          仔细分析以上三种方式,第一种和第二种理论上都是可行的。但是第一种直接存储图片数据量会很大,第二种虽然基本上能够解决第一种情况的问题,但是和第一种一样还存在一个很严重的问题,就是各个不同厂商的的文字或者字符不能够通用,并且换一台计算机,则他不知道绘制规则。第三种就是计算机文字编码的方式了。

          具体做法是:首先把我所想用到的文字都变成一个唯一编码,这个编号发布出去,让所有人都知道,这个编号就称之为文字编码,每个文字对应唯一编码,当计算机绘制文字的时候先根据这个编码去找对应的字体文件中这个编码的图片或者矢量图形来绘制即可。只要大家都遵循这个编码规范,不同的字体就可以使用在不同计算机不同硬件了。

 

         常见的编码有ASCII、GB2312、GBK、Unicode等。这里的重点是GBK和Unicode。

        GB2312码是中华人民共和国国家汉字信息交换用的编码,全称《信息交换用汉字编码字符集——基本集》,是国家标准总局1981年发布。整个字符集分为94个区,每个区有94个位,每个区位上一个字符。区码转成16进制加上2020H转成国际码,国际码加上8080H就可以转成机内码。为了使汉字的编码不重复,每个汉字使用两个字节来表示,高位一个字节对应着区码,低位字节对应着位码,区码和位码构成一个汉字。在GB2312的94个区中,01-09区是特殊字符,16-55区是一级汉字,按照拼音进行排序,56-87区是二级汉字,按照偏旁排序。

        GBK,全称《汉字内码扩展规范》,是由全国信息技术标准化技术委员会制定。GBK编码向下与GB2312编码完全兼容。GBK编码,是在GB2312-80标准基础上的内码扩展规范,使用了双字节编码方案,其编码范围从8140至FEFE(剔除xx7F),共23940个码位,共收录了21003个汉字,完全兼容GB2312-80标准,支持国际标准ISO/IEC10646-1和国家标准GB13000-1中的全部中日韩汉字,并包含了BIG5编码中的所有汉字。

        Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案。Unicode用数字0-0x10FFFF来映射这些字符,最多可以容纳1114112个字符,或者说有1114112个码位。码位就是可以分配给字符的数字。UTF-8、UTF-16、UTF-32都是将数字转换到程序数据的编码方案。

        如下两张图片就可以反映出来GBK编码方式以及GBK和GB2312的关系,图片来自维基百科。

        

 

             在项目中为了可以将文字编码转换成开发环境和语言支持的格式,必须要写GBK和Unicode的编码转换。简单的来说,开发的时候就是给你一个文字,但是你的平台接口是Unicode编码,而你得到的是GBK编码,所以必须进行转换,转换需要一个映射关系,即GBK编码代表的字符,所对应的Unicode编码。

        

             为了获取到GBK编码和Unicode编码之间的对应关系,下面是我写的C#代码。

 

        /// <summary>
        /// 从区位码获取GBK编码
        /// </summary>
        /// <param name="quCode"></param>
        /// <param name="weiCode"></param>
        /// <returns></returns>
        public int QuWeiCode2GBK(int quCode, int weiCode)
        {
            quCode += 0xa0;
            weiCode += 0xa0;

            byte[] bytes = new byte[2];
            bytes[1] = (byte)quCode;
            bytes[0] = (byte)weiCode;
            ushort snum = BitConverter.ToUInt16(bytes, 0);
            return (int)snum;
        }

        /// <summary>
        ///  从GB编码转换到Unicode编码
        /// </summary>
        /// <param name="gbCode"></param>
        /// <returns></returns>
        public int GBK2Unicode(int gbCode)
        {
            byte[] bytes = BitConverter.GetBytes(unchecked((ushort)gbCode));
            Array.Reverse(bytes);
            string word = Encoding.GetEncoding("GBK").GetString(bytes);
            byte[] bs = Encoding.Unicode.GetBytes(word);
            ushort snum = BitConverter.ToUInt16(bs, 0);
            return (int)snum;
        }

        /// <summary>
        /// 从Unicode编码获取BKB编码
        /// </summary>
        /// <param name="uniCode"></param>
        /// <returns></returns>
        public int Unicode2GBK(int uniCode)
        {
            byte[] unCode = BitConverter.GetBytes(unchecked((ushort)uniCode));
            string word = Encoding.Unicode.GetString(unCode);
            byte[] gbCode = Encoding.GetEncoding("GBK").GetBytes(word);
            Array.Reverse(gbCode);
            ushort snum = 0;
            if (gbCode.Length > 1)
                snum = BitConverter.ToUInt16(gbCode, 0);
            if (gbCode.Length == 1)
                snum = (unchecked((ushort)(gbCode[0])));
            return (int)snum;
        }

        /// <summary>
        /// 获取GB2312的所有字符编码
        /// </summary>
        /// <returns></returns>
        public int[] GetBasicCode()
        {
            List<int> gbBasicCode = new List<int>();
            int quCode = 0;
            int weiCode = 0;
            for (int i = 1; i < 100; i++)
            {
                if (i <= 9 || (i >= 16 && i <= 87))
                    quCode = i;
                for (int j = 1; j <= 94; j++)
                {
                    weiCode = j;
                    gbBasicCode.Add(QuWeiCode2GBK(quCode, weiCode));
                }
            }
            return gbBasicCode.ToArray();
        }

        /// <summary>
        /// 获取GBK扩展包3的编码
        /// </summary>
        /// <returns></returns>
        public int[] GetGBK3Code()
        {
            List<int> indexs = new List<int>();
            for (int i = 0x8140; i < 0xa0ff; i++)
            {
                if ((i & 0x000000ff) != 0x7f && (i & 0x000000ff) >= 0x40 && (i & 0x000000ff) < 0xff)
                    indexs.Add(i);
            }
            return indexs.ToArray();
        }

        /// <summary>
        /// 获取GBK 3扩展包的编码和GB2312编码,并按照升序排列
        /// </summary>
        /// <returns></returns>
        public List<int> GetUsedGBKCode()
        {
            int[] basicCodes = GetBasicCode();
            int[] gbk3Codes = GetGBK3Code();
            int[] indexs = new int[basicCodes.Length + gbk3Codes.Length];
            Array.Copy(basicCodes, 0, indexs, 0, basicCodes.Length);
            Array.Copy(gbk3Codes, 0, indexs, basicCodes.Length, gbk3Codes.Length);
            Array.Sort(indexs);

            List<int> delIndexs = new List<int>();
            for (int i = 0; i < indexs.Length; i++)
            {
                int code1 = GBK2Unicode(indexs[i]);
                int code2 = Unicode2GBK(code1);
                if (code2 != indexs[i])
                    delIndexs.Add(i);
            }

            List<int> trIndexs = new List<int>();
            int loop = 0;
            for (int i = 0; i < indexs.Length; i++)
            {
                if (loop < delIndexs.Count && i == delIndexs[loop])
                {
                    loop++;
                    continue;
                }
                trIndexs.Add(indexs[i]);
            }
            return trIndexs;
        }

        /// <summary>
        /// 把GBK编码对应的Unicode编码写进文件里 按照升序排列
        /// 并按照相同的位置在令一个文件里写入Unicode码对应的GBK编码
        /// </summary>
        /// <param name="uniCodes">unicode编码表</param>
        /// <param name="file1">unicode编码表按照16进制的方式写入文件中用逗号分隔</param>
        /// <param name="file2">unicode编码表对应位置的gbk编码,按照16进制方式写入文件</param>
        public void Unicode2GBKMap(int[] uniCodes, string file1, string file2)
        {
            string rn = "";
            int cnt = 0;
            StreamWriter sw1 = new StreamWriter(file1);
            StreamWriter sw2 = new StreamWriter(file2);
            Array.Sort(uniCodes);

            for (int i = 0; i < uniCodes.Length; i++)
            {
                cnt++;
                rn = "";
                if (cnt % 10 == 0)
                {
                    rn = "\r\n";
                }
                string unCodeStr = String.Format("0x{0},{1}", uniCodes[i].ToString("X"), rn);
                sw1.Write(unCodeStr);

                int gbCode = Unicode2GBK(uniCodes[i]);
                string gbCodeStr = string.Format("0x{0},{1}", gbCode.ToString("X"), rn);
                sw2.Write(gbCodeStr);
            }

            sw1.Close();
            sw2.Close();
            MessageBox.Show("转换完成:" + cnt.ToString());
        }

 

                以上贴的是主要的代码,具体界面代码,请直接下载代码工程包,其中效果展示如下:

                代码下载:http://download.csdn.net/detail/devcopper/5356713

 

 

 

 

 

参考资料:http://baike.baidu.com/view/931619.htm?fromId=25421&redirected=seachword

抱歉!评论已关闭.