精华内容
下载资源
问答
  • 为 fopen 指定一个编码,然后写入 wchar_t 字符串,最终写入的文件就是UTF-8编码的了,原理不清楚,估计是 fwrite 时对 wchar_t 做了编码转换(如果写入 char 的话就会乱码)。 #include <stdio.h> #include &...

    为 fopen 指定一个编码,然后写入 wchar_t 字符串,最终写入的文件就是UTF-8编码的了,原理不清楚,估计是 fwrite 时对 wchar_t 做了编码转换(如果写入 char 的话就会乱码)。

    #include <stdio.h>
    #include <tchar.h>
     
    int main()
    {
    	FILE* fp = fopen("test.txt", "wt+,ccs=UTF-8");
     
    	wchar_t* s = _T("hello, 测试测试!");
     
    	fwrite(s, sizeof(wchar_t), wcslen(s), fp);
     
    	fclose(fp);
     
    	return 0;
    }
    
    展开全文
  • C语言UTF8到ANSI和Unicode转换代码

    热门讨论 2013-03-06 15:05:57
    使用C语言,实现UTF8、Unicode、ANSI字符集的互转,用C语言实现头文件和源文件,引入工程可以直接使用。如果在MFC项目中使用该代码,需要更改配置,压缩包中有详细说明。
  • 如题 工作要求将汉字换位utf8编码写入寄存器 不知道该如何</p>
  • Unicode的编码方案又叫Unicode转换格式,简称为UTF(Unicode Transformation Format),包括UTF-16、UTF-32以及UTF-8,其中又属UTF-8使用最为广泛。 3.2.1.UTF-16   UTF-16对应于UCS-2,采用双字节编码BMP内位于...

    1.基础知识

    1.1.字符集

    字符(Character)是各种文字和符号的总称,包括各国家文字、标点符号、图形符号、数字等。 
    字符集(Character set)是多个字符的集合,字符集种类较多,每个字符集包含的字符个数不同,常见字符集有:ASCII字符集、GB2312字符集、BIG5字符集、 GB18030字符集、Unicode字符集等。
    那么为什么会有那么多字符集标准呢?这是因为,很多规范和标准在最初制定时并没有意识到这将会是以后全球普适的准则,或者出于组织本身利益考虑想从本质上区别于现有标准。于是,就产生了那么多具有相同效果但又互不兼容的标准。

    1.2.字符编码

    字符编码(Character encoding),是把字符集中的字符,编码为指定集合中某一对象,以便在计算机中存储和通过网络的传递。
    一般而言,会直接将字符在字符集中的位置,或者说是码点(code point),作为编码后的值。故而,“字符集”和“字符编码”二者是紧密耦合的。因此,某种字符集也可以说成是某种字符编码方式,例如,当我们说到“ASCII”时,既可以指代ASCII字符集,也可以指代ASCII编码。

    2.常用字符集&字符编码

    2.1.ASCII

    ASCII(American Standard Code for Information Interchange,美国信息互换标准编码)是基于基础拉丁字符的一套编码系统。它主要用于显示现代英语。
    ASCII用7bit来编码字符,共128个码位,由于计算机1个字节是8bit,所以最高位为0,即00000000-01111111(0x00-0x7F)。其中有95(十进制32-126)个可打印字符,包括常用的字母、数字、标点符号等,另外还有33(十进制0-31及127)个控制字符。ASCII字符编码对应规则如下:

     

    ASCII是美国人设计的,只能支持基础拉丁字符,但是欧洲不只是用基础拉丁字符的国家该怎么办呢?最简单的办法就是将ASCII没有用到的第8位也用上,这样能表达的字符个数就达到了256个,相较原来,增长了一倍, 这就是EASCII。EASCII基本解决了整个西欧的字符编码问题。但是对于欧洲其它地方如北欧,东欧地区,256个字符还是不够用,因此出现了ISO 8859。为解决256个字符不够用的问题,ISO 8859采取的不再是单个独立的编码规则,而是由一系列的字符集(共15个)所组成,分别称为ISO 8859-n(n=1,2,3…11,13…16,没有12)。其每个字符集对应不同的语言,如ISO 8859-1对应西欧语言,ISO 8859-2对应中欧语言等。EASCII字符编码对应规则如下:(含表格符号、计算符号、希腊字母和特殊的拉丁符号等)

     

    2.2.中文编码

    为了扩充ASCII,以用于显示本国的语言,不同的国家和地区制定了不同的标准,由此产生了GB2312(简体中文),BIG5(繁体中文),JIS(日文)等各自的编码标准。

    2.2.1.GB2312

    为了满足国内在计算机中使用汉字的需要,中国国家标准总局发布了一系列的汉字字符集国家标准编码,统称为GB码,或国标码。其中最有影响的是于1980年发布的《信息交换用汉字编码字符集·基本集》,标准号为GB 2312-1980。GB2312通行于我国内地,新加坡等地也采用此编码标准,并且几乎所有的中文系统和国际化的软件都支持GB2312。 
    GB2312是一个简体中文字符集,收录简化汉字及一般符号、序号、数字、拉丁字母、日文假名、希腊字母、俄文字母、汉语拼音符号、汉语注音字母,共 7445 个图形字符。其中包括6763个汉字,含一级汉字3755个,二级汉字3008个;包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。GB2312对所收录字符进行了“分区”处理,共94个区,区从1(十进制)开始,一直到94(十进制),每区含有94个位,位从1(十进制)开始,一直到94(十进制),共8836(94 * 94)个码位。由此,每个字符都能找到其唯一对应的区位和码位,这种表示方式也称为区位码。各区具体说明如下:

    1

    01-09区收录除汉字外的682个字符,有164个空位(9 * 94 - 682)

    210-15区为空白区,没有使用
    316-55区收录3755个一级汉字(简体),按拼音排序
    456-87区收录3008个二级汉字(简体),按部首/笔画排序
    588-94区为空白区,没有使用

     

    GB2312以区位码为基础,对字符采用双字节编码,其中高字节表示区码,低字节表示位码。由于区码和位码的取值范围均在1-94之间,此范围同ASCII的编码范围冲突。例如汉字‘珀’在GB2312中的区位码为7174(十进制),其双字节表示形式为71、74;而两个ASCII字符‘GJ’的存储码也是71、74,这种冲突将导致解码时的混乱。为解决这个问题,GB2312将区位码均加上0xA0,这样高低字节的第8位都变成了1,进而同ASCII区分开来。具体操作如下图:

     

    例如,‘李’字的区位码为3278(表示在32区,78位),按照上图步骤获取其GB2312编码:

    1、将32(区)转化为十六进制为20;

    2、加上A0为C0;

    3、将78(位)转化为十六进制为4E;

    4、加上A0为EE;

    5、组合区和位,为C0EE;

    6、得到'李'字的GB2312编码为C0EE。

    所以说,GB2312是兼容ASCII的一种编码方式:一个小于127的字符的意义与原来相同,但两个大于127的字符连在一起时,就表示一个汉字,前面的一个字节(高字节)范围从0xA1到0xF7,后面一个字节(低字节)范围从0xA1到0xFE,这样我们就可以组合出7000多个简体汉字了。在这些编码里,还把数学符号、罗马希腊的 字母、日文的假名们都编进去了,连在ASCII里本来就有的数字、标点、字母都统统重新编了两个字节长的编码,这就是常说的”全角”字符,而原来在127以下的那些就叫”半角”字符了。 
    有人可能曾困惑过:GB2312采用双字节编码,原则上来说共有65536个码位,为何实际却只收录字符7445个?现在,我想答案应该是显而易见的:出于兼容ASCII和节省存储容量的考虑,GB2112的双字节编码是变长的,有些字符是单字节表示,如ASCII字符,有些字符是双字节表示,如汉字,由此而来的代价就是损失一部分码位;而且,编码的设计也并非想象的那样,所有字符从头到尾布满整个二维表,其中还预留有一部分空间以作他用。 
    GB2312的出现,基本满足了汉字的计算机处理需要,它所收录的汉字已经覆盖中国大陆99.75%的使用频率。然而,对于人名、古汉语等方面出现的罕用字,GB2312却不能处理,这就导致了后来GBK及GB18030的出现。

    2.2.2.BIG5

    在台湾、香港与澳门地区,使用的是繁体中文字符集。而1980年发布的GB2312面向简体中文字符集,并不支持繁体汉字。在这些使用繁体中文字符集的地区,一度出现过很多不同厂商提出的字符集编码,这些编码彼此互不兼容,造成了信息交流的困难。为统一繁体字符集编码,1984年,台湾五大厂商宏碁、神通、佳佳、零壹以及大众一同制定了一种繁体中文编码方案,即Big5,又称大五码。 
    大五码是一种繁体中文汉字字符集,其中繁体汉字13053个,808个标点符号、希腊字母及特殊符号。大五码采用双字节编码,第1字节范围0x81-0xFE,避开了同ASCII码的冲突,第2字节范围是0x40-0x7E和0xA1-0xFE。因为Big5的字符编码范围同GB2312存在冲突,所以二者并不兼容。Big5字符编码分布表如下:

    编码范围(十六进制)

    符号类别

    8140-A0FE

    保留(用作造字区)

    A140-A3BF

    标点符号、希腊字母及特殊符号

    A3C0-A3FE

    保留(未开放用于造字区)

    A440-C67E

    常用汉字(先按笔划,再按部首排序)

    C6A1-C8FE

    保留(用作造字区)

    C940-F9D5

    非常用汉字(先按笔划,再按部首排序)

    F9D6-FEFE

    保留(用作造字区)

    Big5编码推出后,得到了繁体中文软件厂商的广泛支持,在使用繁体汉字的地区迅速普及使用。目前,Big5编码在台湾、香港、澳门及其他海外华人中普遍使用,成为了繁体中文编码的事实标准。在互联网中检索繁体中文网站,所打开的网页中,大多都是通过Big5编码产生的文档。 
    不过,尽管Big5码内包含一万多个字符,但是没有考虑社会上流通的人名、地名用字、方言用字、化学及生物科等用字,也没有包含日文平假名及片假名字母。

    2.2.3.GBK

    GBK即汉字内码扩展规范,K为扩展的汉语拼音中“扩”字的声母。英文全称Chinese Internal Code Specification。GBK编码标准兼容GB2312,是对GB2312-80的扩展,简、繁体字融于一库。GBK采用双字节表示,总体编码范围为8140-FEFE,首字节在81-FE 之间,尾字节在40-FE 之间。总计23940 个码位,共收入21886个字符,其中汉字(包括部首和构件)21003 个,图形符号883 个。GBK同样兼容ASCII,00–7F范围内单字节表示ASCII字符。

    2.2.4.GB18030

    GB18030,全称GB18030-2000《信息交换用汉字编码字符集基本集的扩充》,是我国政府于2000年3月17日发布的新的汉字编码国家标准,2001年8月31日后在中国市场上发布的软件必须符合本标准。 
    GB18030字符集标准解决了汉字、日文假名、朝鲜语和中国少数民族文字组成的大字符集计算机编码问题。该标准的字符总编码空间超过150万个编码位,收录了27484个汉字,覆盖中文、日文、朝鲜语和中国少数民族文字。满足中国大陆、香港、台湾、日本和韩国等东亚地区信息交换多文种、大字量、多用途、统一编码格式的要求。 
    GB18030标准采用单字节、双字节和四字节三种方式对字符编码,兼容ASCII、GB2312和GBK。

    2.2.5.小结

     

    3.Unicode

    3.1.Unicode字符集

    为什么有Unicode:虽然通过使用不同字符集,我们可以在一台机器上查阅不同语言的文档,但是我们仍然无法解决一个问题:在一份文档中显示世界上所有字符。为了解决这个问题,需要一个全人类达成共识的巨大的字符集,这就是Unicode字符集。 
    Unicode(中文:万国码、国际码、统一码、单一码)是计算机科学领域里的一项业界标准。它对世界上大部分的文字系统进行了整理、编码,使得电脑可以用更为简单的方式来呈现和处理文字。 
    Unicode字符集包含了可能出现的所有字符,每个字符对应一个数字,这个数字即码点(Code Point),如字符‘H’的码点为72,字符‘李’的码点为26446。Unicode包含了1114112个码点,即0x000000-0x10FFFF。世界上所有字符都可以在Unicode字符集中找到对应的唯一码点。 
    Unicode按照使用上的频繁度将码空间划分为17个平面,00-10(十六进制,最高两位),即从0 - 16(十进制),每个平面有65536个码点(2^16),其中最重要的是第一个Unicode平面(码位0x0000-0xFFFF),包含了最常用的字符,该平面被称为基本多语言平面(Basic Multilingual Plane),缩写为BMP,其他平面称为辅助平面(Supplementary Planes),要么是用来表示一些远古时期的文字,要么是留作扩展。Unicode字符集中各个平面的基本情况如下:

     

    在BMP里的所有字符,要用4位十六进制数(例如U+4AE0,共支持六万多个字符);在BMP以外的字符则需要使用5位或6位十六进制数了。 
    Unicode只是一个字符集,只规定了字符所对应的码点,并没有指定字符编码方式,也即从码点到用来存储的比特流之间如何映射。关于这一点,我们不妨回忆一下之前曾经讲过的:一般而言,会直接将字符在字符集中的位置,或者说是码点,作为编码后的值。在这种方式下,字符集和字符编码耦合紧密,限制了字符集的扩展能力。鉴于此,Unicode将字符集和字符编码方案分离开,从字符到码点,再从码点到编码值,作了两次映射。这样,虽然每个字符在Unicode字符集中都能找到唯一确定的码点,但是最终的编码值却是由具体的编码方案决定。例如,同样是对字符“A”进行编码,UTF-8编码得到的值是0x41,而UTF-16(Big-Endian)得到的却是0x0041。

    3.2.编码方案

    Unicode的编码方案又叫Unicode转换格式,简称为UTF(Unicode Transformation Format),包括UTF-16、UTF-32以及UTF-8,其中又属UTF-8使用最为广泛。
    3.2.1.UTF-16
      UTF-16对应于UCS-2,采用双字节编码BMP内位于U+0000至U+D7FF以及U+E000至U+FFFF字符,编码后的值等同于对应的码点;由于BMP内的U+D800至U+DFFF码位不对应于任何字符,UTF-16借助于这些码位,根据一定的规则,采用四字节编码辅助平面内位于U+10000至U+10FFFF的字符。因此,UTF-16是一种变长编码方式。 
      UTF-16可看成是UCS-2的父集。在没有辅助平面字符前,UTF-16与UCS-2所指的是同一的意思。但当引入辅助平面字符后,就称为UTF-16了。现在若有软件声称自己支持UCS-2编码,那其实是暗指它不能支持在UTF-16中超过2字节的字集。对于小于0x10000的UCS码,UTF-16编码就等于UCS码。 
      UTF-16编码分大端序(Big-Endian,简称UTF-16 BE)和小端序(Little-Endian,简称UTF-16 LE)两种,区别在于字节序的不同。例如,汉字“奎”的Unicode码点是594E,“乙”的Unicode码点是4E59。如果我们收到UTF-16字节流“594E”,那么这是“奎”还是“乙”?UTF-16采用BOM(Byte Order Mark,字节序标记)机制来解决这个问题:在Unicode中有两个特殊字符,一个是U+FEFF,表示”ZERO WIDTH NO-BREAK SPACE”;另一个是U+FFFE,它在Unicode中是不存在的字符,所以不应该出现在实际传输中。UTF-16在传输字节流前,先传输一个BOM,这样如果接收者收到FEFF,就表明这个字节流是Big-Endian的;如果收到FFFE,就表明这个字节流是Little-Endian的。 
      以下的例子有四个字符:U+6731(朱)、U+002C(,)、U+807F(聿)、U+2A6A5(四个“龍”组成,无法显示)。

     

    3.2.3.UTF-8 
     UTF-8使用一至六个字节为每个字符编码
    1. 128个ASCII字符只需一个字节编码(U+0000至U+007F)。 
    2. 带有附加符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文及它拿字母则需要两个字节编码(U+0080至U+07FF)。 
    3. 其他基本多文种平面(BMP)中的字符(这包含了大部分常用字,如大部分的汉字)使用三个字节编码(U+0800至U+FFFF)。 
    4. 其他极少使用的Unicode 辅助平面的字符使用四至六字节编码(U+10000至U+1FFFFF使用四字节,U+200000至U+3FFFFFF使用五字节,U+4000000至U+7FFFFFFF使用六字节)。 

     

      总结一下就是:1.对于单字节编码字符,字节的第一位设为0,后面7位为该字符的二进制Unicode码点值,故而UTF-8兼容ASCII;2.对于n字节编码字符(n>1),第一个字节的前n位都设为1,第n+1位设为0,后面字节的前两位一律设为10,剩下的二进制位,全部用该字符的二进制Unicode码点值替代。 
      来看个例子。字符“汉”表示为U+6C49,6C49在0800-FFFF之间,所以要用3字节模板:1110xxxx 10xxxxxx 10xxxxxx。将6C49写成二进制是:0110 110001 001001(不足16位,前面补0), 用这个比特流依次代替模板中的x,得到:11100110 10110001 10001001,转换为十六进制,即UTF-8编码为E6 B1 89。
    UTF-8编码的优点: 
    1. ASCII是UTF-8的一个子集。因为一个纯ASCII字符串也是一个合法的UTF-8字符串,所以现存的ASCII文本不需要转换。为传统的扩展ASCII字符集设计的软件通常可以不经修改或很少修改就能与UTF-8一起使用。 
    2. UTF-8字符串可以由一个简单的算法可靠地识别出来。就是,一个字符串在任何其它编码中表现为合法的UTF-8的可能性很低,并随字符串长度增长而减小。举例说,字符值C0、C1、F5至FF从来没有出现。为了更好的可靠性,可以使用正则表达式来统计非法过长和替代值。 
    UTF-8编码的缺点: 
    1. 与其他Unicode编码相比,特别是UTF-16,在UTF-8中ASCII字符占用的空间只有一半,可是在一些字符的UTF-8编码占用的空间就要多出1/3,特别是中文、日文和韩文(CJK)这样的方块文字。
      由于在UTF-8编码中,其自身已经带了控制信息,如1110xxxx 10xxxxxx 10xxxxxx ,其中1110就起到了控制作用,所以不需要额外的BOM机制,但可以用BOM来表明编码方式。字符”ZERO WIDTH NO-BREAK SPACE”的UTF-8编码是0xEFBBBF,所以如果接收者收到以0xEFBBBF开头的字节流,就知道这是UTF-8编码了。但是需要注意,不是所有软件或者程序都能正确处理BOM标记,所以我们不推荐对UTF-8编码的文件加上BOM。

    4.判断字符串是否是utf-8编码格式

    int utf8_check(const char* str,size_t length)
    {
        size_t i = 0;
        int nBytes = 0;UTF8可用1-6个字节编码,ASCII用一个字节
        unsigned char ch = 0;
        bool bAllAscii = true;//如果全部都是ASCII,说明不是UTF-8
        while(i < length)
        {
            ch = *(str + i);
             if ((ch & 0x80) != 0)
                bAllAscii = false;
            if(nBytes == 0)
            {
                if((ch & 0x80) != 0)
                {
                    while((ch & 0x80) != 0)
                    {
                        ch <<= 1;
                        nBytes ++;
                    }
                    if((nBytes < 2) || (nBytes > 6))
                    {
                        return 0;
                    }
                    nBytes --;
                }
            }
            else
            {
                if((ch & 0xc0) != 0x80)
                {
                    return 0;
                }
                nBytes --;
            }
            i ++;
        }
        if(bAllAscii)
            return false;
        return (nBytes == 0);
    }
    展开全文
  • UTF8-GBK编码互转(C)

    2017-12-14 10:31:43
    这是一个应用于UTF8-GBK编码互转的代码,使用用C语言编写的,不依赖任何API,可直接调用。
  • C语言实现GB2312和UTF8之间的编码转换

    千次阅读 2020-11-17 20:05:10
    C语言实现GB2312和UTF8之间的编码转换 GB2312 GB2312编码适用于汉字处理、汉字通信等系统之间的信息交换,基本集共收入汉字6763个和非汉字图形字符682个。GB2312中对所收汉字进行了“分区”处理,字符集分成94个区,...

    C语言实现GB2312和UTF8之间的编码转换

    GB2312

    GB2312编码适用于汉字处理、汉字通信等系统之间的信息交换,基本集共收入汉字6763个和非汉字图形字符682个。GB2312中对所收汉字进行了“分区”处理,字符集分成94个区,每区含有94个汉字/符号,这种表示方式也称为区位码。
    01-09区为特殊符号。
    16-55区为一级汉字,按拼音排序。
    56-87区为二级汉字,按部首/笔画排序。
    10-15区及88-94区则未有编码。
    举例来说,“啊”字是GB2312之中的第一个汉字,它的区位码就是1601。每个汉字及符号以两个字节来表示。第一个字节称为“高位字节”(也称“区字节)”,第二个字节称为“低位字节”(也称“位字节”)。

    UTF-8

    UTF-8(8位元,Universal Character Set/Unicode Transformation Format)是针对Unicode的一种可变长度字符编码。UTF-8使用1~4字节为每个字符编码:
    1)一个US-ASCIl字符只需1字节编码(Unicode范围由U+0000~U+007F)。
    2)带有变音符号的拉丁文、希腊文、西里尔字母、亚美尼亚语、希伯来文、阿拉伯文、叙利亚文等字母则需要2字节编码(Unicode范围由U+0080~U+07FF)。
    3)其他语言的字符(包括中日韩文字、东南亚文字、中东文字等)包含了大部分常用字,使用3字节编码。
    4)其他极少使用的语言字符使用4字节编码。

    由此可知,对于中文,GB2312编码占用2个字节,UTF-8编码占用3个字节。

    linux下编码工具

    1. 命令行工具
    iconv -f encoding -t encoding inputfile
    

    有如下选项可用:

    输入/输出格式规范:
    -f, --from-code=名称 原始文本编码
    -t, --to-code=名称 输出编码
    
    信息:
    -l, --list 列举所有已知的字符集
    
    输出控制:
    -c 从输出中忽略无效的字符
    -o, --output=FILE 输出文件
    -s, --silent 关闭警告
    --verbose 打印进度信息
    

    示例:下面的命令是将一个utf8编码的文件转换为一个unicode编码的文件

    iconv -f utf-8 -t gb2312 utf8file.txt  -o gb2312file.txt
    
    1. C语言调用iconv库
      下载libiconv库
      根据个人开发板,交叉编译出动态库。
      Ubuntu下好像可以直接包含头文件使用。
    #include <iconv.h>
    

    三个主要函数:

    iconv_t iconv_open(const char *tocode, const char *fromcode);
    

    此函数说明将要进行哪两种编码的转换,tocode是目标编码,fromcode是原编码,该函数返回一个转换句柄,供以下两个函数使用。

    size_t iconv(iconv_t cd,char **inbuf,size_t *inbytesleft,char **outbuf,size_t *outbytesleft);
    

    此函数从inbuf中读取字符,转换后输出到outbuf中,inbytesleft用以记录还未转换的字符数,outbytesleft用以记录输出缓冲的剩余空间

    注意:inbuf和outbuf都必须是有存储空间的不能定义为常量,如:char *inbuf = “abc” 或者是char *outbuf = "123"这样定义都是错误的。另外inbuf,inbytesleft,outbuf,outbytesleft这几个参数在使用过程中都会改变,最好是先保存一下原值,然后再使用。

    int iconv_close(iconv_t cd);
    

    此函数用于关闭转换句柄,释放资源。

    代码示例:

    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    #include "iconv.h"
    
    //iInLen的长度不包括\0,应该用strlen。返回值是处理后的sOut长度
    static int Utf8ToGb2312(char *sOut, int iMaxOutLen, const char *sIn, int iInLen)
    {
        char *pIn = (char *)sIn;
        char *pOut = sOut;
        size_t ret;
        size_t iLeftLen=iMaxOutLen;
        iconv_t cd;
    
        cd = iconv_open("gb2312", "utf-8");
    
        if (cd == (iconv_t) - 1)
        {
            return -1;
        }
    	
        size_t iSrcLen=iInLen;
        ret = iconv(cd, &pIn,&iSrcLen, &pOut,&iLeftLen);
    	
        if (ret == (size_t) - 1)
        {
            iconv_close(cd);
            return -1;
        }
    
        iconv_close(cd);
    
        return (iMaxOutLen - iLeftLen);
    }
    
    //iInLen的长度不包括\0,应该用strlen。返回值是处理后的sOut长度
    static int Gb2312ToUtf8(char *sOut, int iMaxOutLen, const char *sIn, int iInLen)
    {
        char *pIn = (char *)sIn;
        char *pOut = sOut;
        size_t ret;
        size_t iLeftLen=iMaxOutLen;
        iconv_t cd;
    
    
        cd = iconv_open("utf-8", "gb2312");
    	
        if (cd == (iconv_t) - 1)
        {
            return -1;
        }
        size_t iSrcLen=iInLen;
    	
        ret = iconv(cd, &pIn,&iSrcLen, &pOut,&iLeftLen);
        if (ret == (size_t) - 1)
        {
            iconv_close(cd);
            return -1;
        }
    
        iconv_close(cd);
    
        return (iMaxOutLen - iLeftLen);
    }
    
    int main()
    {
    	int nRtn = 0;
    	char* pszOri = "这是一个中文测试例程";
    
    	printf("byStr[%d]: %s\n", strlen(pszOri), pszOri);
        
        char pszDst[50] = {0};
        
        int iLen = Utf8ToGb2312(pszDst, 50, pszOri, strlen(pszOri)); // Utf8ToGb2312
    
    	printf("iLen: %d    %s\n", iLen, pszDst);
    
    	printf("-----------\n");
        
        char pszGbDst[50] = {0};  
        int iNewLen = Gb2312ToUtf8(pszGbDst, 50, pszDst, iLen); // Gb2312ToUtf8  
    
    	printf("iNewLen: %d    %s\n", iNewLen, pszGbDst);
    
    	return nRtn;
    }
    

    以上代码在Linux下编译,记得加上-liconv,代码先将UTF-8转换为GB2312,再从GB2312转为UTF-8,在SecureCRT下,按照GB2312编码方式显示,可以看到iLen后面的中文打印,按照UTF-8编码方式打印,可以看到byStr以及iNewLen后面的中文打印。

    参考:Linux下 GB2312和UTF8转换接口

    展开全文
  • 1. ASCII编码 百度百科 - “ASCII ((American Standard Code for Information Interchange): 美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换...

    1. ASCII编码

    百度百科  -  “ASCII ((American Standard Code for Information Interchange): 美国信息交换标准代码)是基于拉丁字母的一套电脑编码系统,主要用于显示现代英语和其他西欧语言。它是最通用的信息交换标准,并等同于国际标准ISO/IEC 646。ASCII第一次以规范标准的类型发表是在1967年,最后一次更新则是在1986年,到目前为止共定义了128个字符”

    ASCII码使用一个字节表示128种字符,其中0x00 ~ 0x1F是不可打印(显示)字符,或者说是控制字符,例如:0x08为‘\b’,表示退格的意思(Backspace),0x0A为‘\n’,表示换行的意思。0x20 ~ 0x7F为可打印字符,全部可打印字符有:

     !"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\]^_`abcdefghijklmnopqrstuvwxyz{|}~

    使用ASCII码可以用一个字节表示一个英文字母、数字或常用符号,但是无法表示中文、日文等字符。

    可以看出来,所有ASCII字符的范围为0x00 ~ 0x7F,二进制表示为B0000 0000 ~ B0111 1111,最高位永远是0,如果某个字符的MSB是1的话,那么这个字符就不在ASCII编码规则之内,也就是说它不是一个ASCII字符。

    2. GB2312编码

    GB2312编码是第一个汉字编码国家标准,由中国国家标准总局1980年发布,1981年5月1日开始使用。GB2312编码共收录汉字6763个,其中一级汉字3755个,二级汉字3008个。同时,GB2312编码收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。

    上面说了,如果某个字符的MSB是1的话,那么这个字符就不是一个ASCII字符,利用这个特性就可以设计一套编码方式,使得其可以扩展更多的字符同时兼容ASCII编码格式。

    GB2312就是这么设计的。如果MSB为1的话,则表示其为GB2312编码格式(也可能是其它编码格式)。GB2312编码格式规定一个GB2312字符占用两个字节(大端模式),第一个字节(高字节)的取值范围为0xA1 ~ 0xFE,一共94个取值,第二个字节(低字节)的取值范围也是0xA1 ~ 0xFE,一共94个取值。所以两个字节的组合一共有 94 * 94 = 8836个组合,也就是说一共可以表示8836个字符。

    GB2312编码对所收录字符进行了“分区”处理,使用上述的两个字节分别表示94个区和94个位,确定了区码和位码就能定位到具体的汉字,这种表示方式也称为区位码:

    01-09区收录除汉字外的682个字符。
    10-15区为空白区,没有使用。
    16-55区收录3755个一级汉字,按拼音排序。
    56-87区收录3008个二级汉字,按部首/笔画排序。
    88-94区为空白区,没有使用。
    举例来说,“啊”字是GB2312编码中的第一个汉字,它位于16区的01位,所以它的区位码就是1601。

    具体的汉字分区参考文章:GB2312 编码范围, GB2312 编码表。计算机在处理以GB2312格式编码的字符串的时候会先判断当前字符属于ASCII字符还是属于GB2312字符,如果是GB2312字符的话,会一次性处理两个字节作为一个字符。

    3. UTF8编码(Unicode transform format)

    仿佛GB2312编码规范还是不够用,虽然它可以兼容ASCII码,但是无法兼容其它国家的字符。所以UTF8编码格式显得更加先进。

    UTF8编码参考文章:计算中心

    要了解UTF8编码就必须了解Unicode编码,百度百科  -  “统一码,也叫万国码、单一码(Unicode)是计算机科学领域里的一项业界标准,包括字符集、编码方案等。Unicode 是为了解决传统的字符编码方案的局限而产生的,它为每种语言中的每个字符设定了统一并且唯一的二进制编码,以满足跨语言、跨平台进行文本转换、处理的要求。1990年开始研发,1994年正式发布1.0版本,2020年发布13.0版本。”。现在用的是UCS-2,即2个字节编码,而UCS-4是为了防止将来2个字节不够用才开发的。

    说白了,Unicode编码就是把地球上的所有字符都统一编码到两个字节的空间里面去,所以UCS-2标准的Unicode最多可以容纳65536个字符。那么我们用Unicode编码直接表示字符串的话,由于Unicode编码不兼容ASCII码,比如“我”子的Unicode编码为0x6211,其两个字节单独拿出来都能对应一个ASCII码,所以在进行文本处理的时候,如果Unicode编码和ASCII编码格式混合存在,那么遇到0x6211的时候,不知道这是两个ASCII码还是一个Unicode码,因此使用Unicode编码不兼容ASCII编码。所以每个字符不管是英文字母还是汉字,都占用两个字节的空间。这时候存在空间浪费,因为很多时候纯英文文章,如果使用Unicode编码的话占用的空间是使用ASCII编码的两倍,如果使用UCS-4标准,一个Unicode字符需要4个字节,空间浪费更过分。所以出现了基于Unicode编码的的编码格式UTF8。

    简单来说,UTF-8是Unicode的一种实现方式,其兼容ASCII编码。具体的编码格式如下图,图片第一列为Unicode编码的地址空间(0x0000 ~ 7FFF),第三列为对应的UTF8编码格式。

    1、其中Unicode(0x0000 ~ 0x007F)的地址空间转换成UTF8编码空间只需要1个字节,也就是ASCII码的空间。

    2、Unicode(0x0080 ~ 0x07FF)的地址空间转换成UTF8编码空间需要2个字节,第一个字节的最高三位为“前导码”为 “110”,这高三位中有两个bit ‘1’,表示该字符占用两个字节,也就是除了当前字节外,后面还剩一个字节(同样的,如果第一个字节的最高位为 “1110” 的话,表示该字符占用3个字节,后面还剩两个字节),该字符剩下的字节的前导码固定为 “10”。那么,第一个字节剩下的5位加上第二个字节剩下的6位一共11个位可以表示 2^11 = 2048 个字符。

    3、Unicode(0x0800 ~ 0xFFFF)的地址空间转换成UTF8编码空间需要3个字节,第一个字节的最高三位为“前导码”为 “1110”,表示该字符占用3个字节,后面还剩两个字节。那么,第一个字节剩下的5位,第二、第三个字节个剩下的6位一共 5 + 6 + 6 = 17 个位,足够表示Unicode(0x0800 ~ 0xFFFF)16位的地址空间。这个地址空间包含了绝大部分的字符,包括汉字。所以使用UTF8编码汉字,一个汉字占用3个字节,一个ASCII码占用一个字节。

    4、剩下的Unicode地址空间原理上和上面的一样,只是前导码不一样而已。这个地址空间很少用到。

    另外,UTF-8编码中还有带BOM和不带BOM的区别,做个测试,两个内容相同的文件,一个以UTF-8带BOM编码,另一个以UTF-8不带BOM编码:

    前者占用6字节的存储空间,后者占用3字节的存储空间。使用HEX编辑模式打开看看(Notpad++插件):

    可以看到,UTF-8带BOM编码的文件前面多了0xEF 0xBB 0xBF这三个字节。

    “UTF-8不需要BOM来表明字节顺序,但可以用BOM来表明编码方式。字符”ZERO WIDTH NO-BREAK SPACE“的UTF-8编码是EF BB BF。所以如果接收者收到以EF BB BF开头的字节流,就知道这是UTF-8编码了。”

    传输过程中,若收到 “EF BB BF”,则表示后面传输的是UTF-8文本。BOM不是必须的,一般都是采用UTF-8无BOM编码方式。

    另外,关于UTF8、UTF16、UTF32区别,参考文章:字符编码的概念(UTF-8、UTF-16、UTF-32都是什么鬼)_顾小暖的博客-CSDN博客

    1、UTF8编码允许一个字符的最小可以使用一个字节编码,例如ASCII字符。处理速度最慢,存储空间最小。

    2、UTF16需要2个或者4个字节表示一个字符,不兼容ASCII编码。对于 Unicode 编号范围在 0 ~ FFFF 之间的字符,UTF-16 使用两个字节存储,并且直接存储 Unicode 编号,不用进行编码转换,这跟 UTF-32 非常类似。对于 Unicode 编号范围在 10000~10FFFF 之间的字符,UTF-16 使用四个字节存储,具体来说就是:将字符编号的所有比特位分成两部分,较高的一些比特位用一个值介于 D800~DBFF 之间的双字节存储,较低的一些比特位(剩下的比特位)用一个值介于 DC00~DFFF 之间的双字节存储。处理速度中等,存储空间中等。

    3、UTF-32 是固定长度的编码,始终占用 4 个字节,足以容纳所有的 Unicode 字符,所以直接存储 Unicode 编号即可,不需要任何编码转换。浪费了空间,提高了效率,处理速度最快,存储空间最大。

    展开全文
  • WideCharToMultiByte函数映射一个unicode字符串到一个多字节字符串。 函数原型: int WideCharToMultiByte UINT CodePage, //指定执行转换的代码页 DWORD dwFlags, //允许你进行额外的控制,它会影响使用了读音...
  • C语言实现中文编码转换一、GBK、UNICODE、UTF8之间编码的关系二、UNICODE、UTF8之间转化实现三、UNICODE、GBK之间的转化四、编码对照表五、完整代码 一、GBK、UNICODE、UTF8之间编码的关系 GBK:GBK全名为汉字内码...
  • 用二进制方式创建一个文件,然后写UTF-8文件头(必须在后续之前)  char header[3] = {0xef, 0xbb, 0xbf}; // UTF-8 file header  FILE * fp = fopen(pszFile, "w+b"); fwrite(line, sizeof(char), ...
  • /* filename: isutf8.c Time: 2016-12-9 20:27 Author: Albert Wang email: albertofwb@gmail.com Function: detect whether a text file's encoding is utf-8 format */ #...
  • Utf8转GB2312

    2018-12-13 11:40:53
    Utf8转GB2312,FileEncodingTransform.exe FileEncodingTransform.vshost.exe
  • C编译时编码设置(UTF-8、GBK编码格式) ...打开设置,搜索encoding,设置默认的文本字符编码,在此处选择GBK编码时新建的文件默认为GBK编码,在此处选择UTF-8编码时,默认采用UTF8编码。 在上一步骤中,我默认设
  • GB2312转UTF-8(C代码)

    2020-12-04 11:41:09
    本资源为GB2312转UTF-8C语言代码,实现方式为查表的方式,提供了可以调用的接口,里面有makefile,用于别的平台自行修改。
  • C语言文件读写函数总结

    千次阅读 多人点赞 2018-04-30 23:51:59
    1、字符写入文件函数 fputc 2、从文件中读取字符 fgetc 二、字符串的读写 1、字符串写入文件函数 fputs 2、从文件中读取字符 fgets 三、块数据读写 1、向文件中写入块数据fwrite 2、从文件中读取块数据fread ...
  • C++将UTF-8编码文件转化为GB2312编码

    千次阅读 2019-10-18 13:54:03
    C++将UTF-8编码文件转化为GB2312编码 我需要对一个html网页进行解析,html是使用UTF-8编码的。但是,我使用的visual Studio 19是使用gb2312进行编码的。当读入html文件并在控制台上输出时,中文自然全部变成了...
  • UTF-8, Unicode, GB2312格式串转换之C语言版  (申明:此文章属于原创,若转载请表明作者和原处链接 )   /* author: wu.jian (吴剑) English name: Sword  /* date: 2007-12-13  /* purpose: 知识共
  • Unicode就是这样一种字符编码系统,它具有由128个三维组(带有由大量字符编码方案的方法支持的94,140个定义好的字符值)组成的四维编码空间,在Linux中更流行的字符编码方案是Unicode转换格式UTF-8。 参考资料 您...
  • 利用libiconv在windows下实现汉字utf8编码和gbk编码之间的转换,内涵完整的VS2013工程
  • 最近把播放器的固件升级了,结果歌词全部变成了乱码,中文出现乱码基本都是编码格式的问题。 一个一个的手动修改太麻烦了,就了一个简单的java代码来实现批量转换一下。 主要完成的 import info.monitorenter....
  • 文章结构:本文的先介绍了常见的几种编码格式:ANSI,Unicode,UTF-8,在进行编码转换之前,需要先判断文件编码格式,在编码转换完成之后,需要将文件保存为UTF-8编码格式的文件。 文本文件编码格式介绍 在计算机...
  • 批量或单个将.c.h.css.txt.java.cs等所有常用格式及任意自定义文本由ansi转为utf-8编码
  • By: Ailson Jack ...C语言向Console输出UTF-8编码的中文内容时,cmd通常会乱码而Linux的终端却不会。 原因就是cmd的默认编码方式不是utf8,而Linux是。 让cmd不乱码的方式只需要引入stdlib.h头文件
  • linux下C语言utf-8编码与gb2312转换代码 2010-04-02 14:09 int code_convert(char *from_charset, char *to_charset, char *inbuf, int inlen, char *outbuf, int outlen) { iconv_t cd...
  • C语言实现windows1251编码utf-8编码

    千次阅读 2014-09-19 21:40:57
    windows1251是俄罗斯本地的一种编码,不通用

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 20,950
精华内容 8,380
关键字:

c语言utf8编码写文件

c语言 订阅