字符编码及文件读取的基础知识

这是以前写的一点笔记,把它转过来。

1、二进制文件和文本文件

首先看二段代码:生成一个二进制文件和一个文本文件。打开一个二进制文件:test.dat,写入整数1234,其对应的十六进制为04 D2。

 

    FILE *pfile;
    int ntest = 1234;
    if(NULL == (pfile=fopen("test.dat","wb")))
    {
        printf("can't write file:test.dat");
        return(1);
    }
    fwrite(&ntest,sizeof(int),1,pfile);
    fclose(pfile);

 

ultraedit打开,可以看见:

 

然后:再次写一个文件:

    FILE *pfile;
    int ntest = 1234;
    if(NULL == (pfile=fopen("test.bin","w")))
    {
        printf("can't write file:test.dat");
        return(1);
    }
//fwrite(&ntest,sizeof(int),1,pfile);
    fputs("1234", pfile);
    fclose(pfile);

打开后显示:

 

 

  世界上本没有文本文件,只说用的人多了才有了文本文件的概念。所有存储在计算机上的文件都是以二进制比特流的形式存在。有些比特流的特定多少位表示一个能可见的字符(比如说o1100101表示A),那么组成的文件就是通常所说的文本文件,除此之外的就是二进制文件了,二进制文件通常打开都是乱码,是因为你的工具(如记事本等)往往按照一个字节一个字节去读取二进制比特流,而有时候这个字节代表了一个不可见的字符,比如上面的D2。我们平时用的docbmp等文件都是二进制文件。

2、二进制文件和文本文件的打开方式

 

  文本方式和二进制方式仅仅是一种方式,不是说文本方式用来打开文本文件,二进制方式打开二进制文件。这两种方式的惟一区别就是:当利用文本方式打开文件时,遇到回车换行就转换成’\n’(windows需要转换,而linux系统不需要,这是因为windowslinux表示换行的标识符不一样,前者是\r\n,而后者是\n,c语言规定的是一样的,在linux下面这两种方式没有区别。而且转化的工作由编译器完成,操作系统只负责处理数据流),而二进制方式没有这种转换。文本文件里的每个字节数据(当然也是用二进制存储在计算机上)一般都表示一个ascii(这里暂时只说ansi文本格式,对于unicode则不同了,后面会讲到),而二进制文件里的每个字节数据可能表示一个ascii也可能不是,当在ascii表中可以找到对应的字符时,你用文本编辑器打开时就能看见对应的字符,如果找不到就是乱码。

 

freadfwrite往往用于读取和写入二进制文件,当然也可以读取和写入文本文件;反之,fgetsfputs往往用于文本文件的读取和写入,当然也可以读取和写入二进制文件。一切取决于你写入的数据格式和对读取的内容做什么样的解析。计算机只负责和二进制数据打交道,它不管你的二进制数据表示什么。

 

 

    FILE *pfile;
    char buf[1024] = {'\0'};
    int nCount;
    if(NULL == (pfile=fopen("test.txt","r")))

    //if(NULL == (pfile=fopen("test.txt","rb")))
    {
        printf("can't write file:test.dat");
        return(1);
    }
    //fread(&ntest,sizeof(int),1,pfile);
    fgets(buf, 1024, pfile);
    //printf("%d\n",ntest);
    for (int na=0; na<1024 && buf[na]!=0; na++)
    {
        int ntemp = buf[na];
        ntemp &= 255;
        printf("%0.2x\n",ntemp);
    }
    fclose(pfile);

 

用文本方式打开结果:

 

用二进制方式打开:

3,Ansi/gbk/Unicode/utf-8

 

 

Ansi:最初是美国制定的一套标准,也就是ansiascii,0-127表示一个字符。

 

GBK中国为了支持汉字,用两个字节表示一个汉字。在判断这个字节大于127,说明是一个汉字编码的开始,然后读取下一个字节,组合在一起形成一个汉字。GBK里面小于127的字节表示的含义与ASCII一样。

 

Unicode:为了统一世界上各个国家的字符编码集,制定了一个统一的编码方案,概括了所有的语言字符,用2个字节表示。

 

Utf-8:实际上是unicode的一种实现形式。因为unicode只是规定了字符的编码内容,没有规定字符的存储方式。网络上的数据流往往以字节流的形式发送或者接收,utf-8规定了这些字节流的存储方式。

 

规定了这些字节流的存储方式。

 

UTF-8

 

0000 - 007F                  0xxxxxxx

 

0080 - 07FF                  110xxxxx 10xxxxxx

 

0800 – FFFF                 1110xxxx 10xxxxxx 10xxxxxx

 

英文符号用1个字节表示,汉字一般用3个字节表示。实际上的对于英文,utf-8ascii节省空间,而汉字则相反。

 

接下来出现了一个问题,当解析一个文本时,如何得知其编码方式,这里就是由各种文件的头标志决定的:

 

低位地址---->高位地址

 

EF BB BF                  UTF-8
FE FF                      UTF-16/UCS-2, big endian

 

FF FE                       UTF-16/UCS-2, little endian(小高高)

FF FE  00 00            UTF-32/UCS-4, little endian.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值