文件编码方式

ASCII

	计算机的机器语言只有 0 和 1,每个代表一位(bit)。当美国人要用计算机存放人类语言的字符时就将8bit组成一个字节(byte),总共可存储2^8(即256)个字符,从0000000到11111111,其中包括26个英文字母,数据及一些常用的符合,只保存128个字符,剩余的可用于扩展,称之为ASCII编码。

GB2312 -> GBK -> GB18030

	在中国,由于汉字数量太多,8bit不够存放这么多字符,就对其进行扩展,用两个字节(16bit)表示一个汉字,前128个字符保持不变,在后边追加了中文字符,称之为GB2312 -> GBK -> GB18030(三种字符集是包含关系,因为不断往字符集中插入新的字符,扩展出来的)。

unicode(简称UCS)

	由于每个国家都像中国一样,都有自己的字符集,造成互不相通,因此ISO(国际标谁化组织)规定必须用两个字节,也就是16位(2^16即65536)来统一表示所有的字符,ASCII字符集的编码在unicode中保持不变,只是将其扩展为两个字节,然后将其它国家的字符都添加进去。
	补充:Unicode有两套标准,一套叫UCS-2(Unicode-16),用2个字节为字符编码,另一套叫UCS-4(Unicode-32),用4个字节(实际上只用了31位,最高位必须为0)为字符编码。目前常用的UCS-2,它可以表示的字符数为2^16=65535,基本上可以容纳所有的欧美字符和绝大部分的亚洲字符 。 但是很明显,如果要支持所有的亚洲字符,必须用UCS-4

utf-8

	由于unicode只是字符集的编码方式,并没有规定在文件中如何存储。当然也可以按照编码方式存放,但有个问题,一个英文字母只用一个字节就足够了,如果一个文件全是英文,那么它就多占用了一倍的空间。所有发明了utf-8的存储方式,它是一种变长的编码方式。
	注:utf-8只是unicode的一种存储方式,下面是对应的转化关系
Unicode符号范围 | UTF-8编码方式
(十六进制) | (二进制)
--------------------+---------------------------------------------
0000 0000-0000 007F | 0xxxxxxx
0000 0080-0000 07FF | 110xxxxx 10xxxxxx
0000 0800-0000 FFFF | 1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF | 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx

Little endian和Big endian

	文件存储字符时,有Little endian和Big endian这两种顺序,但怎么知道计算机是如何存储的呢?Unicode规范中定义,每一个文件的最前面分别加入一个表示编码顺序的字符,这个字符的名字叫做”零宽度非换行空格“(ZERO WIDTH NO-BREAK SPACE),用FEFF表示。这正好是两个字节,而且FF比FE大1。
	如果一个文本文件的头两个字节是FE FF,就表示该文件采用大头方式;如果头两个字节是FF FE,就表示该文件采用小头方式。

	测试一下:
	新建一个文本文件,内容“联通”(unicode编码 \u8054\u901a),依次采用ANSI,Unicode,Unicode big endian 和 UTF-8编码方式保存
	
	ANSI:文件的编码就是4个字节“\u8054\u901a”,这正是“”的GB2312编码,这也暗示GB2312是采用大头方式存储的
	Unicode:编码是6个字节“FF FE 25 4E”,其中“FF FE”表明是小头方式存储,真正的编码是 \u8054\u901a
	Unicode big endian:编码是6个字节,其中“FE FF”表明是大头方式存储
	UTF-8:编码是9个字节“EF BB BF E4 B8 A5”,前3个字节“EF BB BF”表示这是UTF-8编码,后6个字节就是“联通”的具体编码,它的存储顺序与编码顺序是一致的。unicode到utf-8的具体转换可参照上边的 “Unicode符号范围 | UTF-8编码方式”

在这里插入图片描述
在这里插入图片描述运行结果

#include <iostream>
#include <unistd.h>
#include <cstdio>
#include <cstring>

int readfile(char *filename);

int main(int argc, char *argv[])
{
    //ASCII
    char filepath_ANSI[] = "C:\\Users\\MaoMao\\Desktop\\ASCII.txt";
    readfile(filepath_ANSI);

    //Unicode big endian
    char filepath_unicode_BE[] = "C:\\Users\\MaoMao\\Desktop\\Unicode big endian.txt";
    readfile(filepath_unicode_BE);

    //Unicode little endian
    char filepath_unicode_LE[] = "C:\\Users\\MaoMao\\Desktop\\Unicode little endian.txt";
    readfile(filepath_unicode_LE);

    //utf-8
    char filepath[] = "C:\\Users\\MaoMao\\Desktop\\utf-8.txt";
    readfile(filepath);

    return 0;
}

int readfile(char *filename)
{
    printf("read file %s\n", filename);

    char buff[255];
    unsigned filesize;

    FILE *fp = fopen(filename, "rb+");
    if( fp == NULL )
    {
        printf("open file error.\n");
        perror("fopen");
        return -1;
    }

    //fputs("string", fp);
    //fprintf(fp, "test");

    fseek(fp, 0, SEEK_SET);
    memset(buff, 0, sizeof(buff));
    if( NULL == fgets(buff, sizeof(buff), fp))
    {
        perror("fgets");
        return -1;
    }
    filesize = strlen(buff);
    printf("file size : %d\n", filesize);

    int i = 0;
    while(i < filesize)
    {
        printf("%x\n", buff[i++]);
    }
    printf("\n");

    fclose(fp);
    return 0;
}

编码转换工具http://tool.chinaz.com/tools/unicode.aspx

参考:https://blog.csdn.net/lvxiangan/article/details/8151670

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值