这是以前写的一点笔记,把它转过来。
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。我们平时用的doc,bmp等文件都是二进制文件。
2、二进制文件和文本文件的打开方式
文本方式和二进制方式仅仅是一种方式,不是说文本方式用来打开文本文件,二进制方式打开二进制文件。这两种方式的惟一区别就是:当利用文本方式打开文件时,遇到回车换行就转换成’\n’(windows需要转换,而linux系统不需要,这是因为windows与linux表示换行的标识符不一样,前者是\r\n,而后者是\n,与c语言规定的是一样的,在linux下面这两种方式没有区别。而且转化的工作由编译器完成,操作系统只负责处理数据流),而二进制方式没有这种转换。文本文件里的每个字节数据(当然也是用二进制存储在计算机上)一般都表示一个ascii(这里暂时只说ansi文本格式,对于unicode则不同了,后面会讲到),而二进制文件里的每个字节数据可能表示一个ascii也可能不是,当在ascii表中可以找到对应的字符时,你用文本编辑器打开时就能看见对应的字符,如果找不到就是乱码。
fread和fwrite往往用于读取和写入二进制文件,当然也可以读取和写入文本文件;反之,fgets和fputs往往用于文本文件的读取和写入,当然也可以读取和写入二进制文件。一切取决于你写入的数据格式和对读取的内容做什么样的解析。计算机只负责和二进制数据打交道,它不管你的二进制数据表示什么。
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:最初是美国制定的一套标准,也就是ansi的ascii,用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-8比ascii节省空间,而汉字则相反。
接下来出现了一个问题,当解析一个文本时,如何得知其编码方式,这里就是由各种文件的头标志决定的:
低位地址---->高位地址
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.