一直以来都奇怪fread里r与b的区别在哪?
今天在csdn上看到一篇文章说了下,可惜只有寥寥几行,不甚明了。
于是自己试验了下,从网上也看了些说明。
纸上得来终觉浅,绝知此事要躬行。
data.txt就是在windows下建立的记事本,敲了几个enter保存即可。
先od下看下:
$ od data.txt -x
0000000 0a0d 0a0d 0a0d 0a0d 0a0d 0a0d 0a0d 0a0d
0000020 0a0d 0a0d 0a0d 0a0d
0000030
测试程序:
/*
* =====================================================================================
* Filename: test.c
* Description: test for rb&r in fread()
* Created: 04/23/2012 06:47:07 PM
* Compiler: gcc
*
* Author: zhy (), [email protected]
* Company:
* =====================================================================================
*/
#include<stdio.h>
intmain()
{
FILE*fp =fopen("data.txt","r");
intl =fseek(fp,0,SEEK_END);
printf("l: %d",l);
longcs =ftell(fp);
printf("cs: %d\n",cs);
fseek(fp,0,SEEK_SET);
charstr[100];
size_t reads =fread(str,1,cs,fp);
printf("reads: %d\n",reads);
inti =0;
for(i=0;i<reads; ++i) {
if(i%10==0)
printf("\n");
printf("%x",str[i]);
}
printf("\n");
return0;
}
程序输出:
$ ./test
l: 0cs: 24
reads: 24
dadadadada
dadadadada
dada
如果fread参数改为rb:
编译没问题,运行结果是一样的、、、
很奇怪, 于是换到windows下面来编译运行:
“r”打开时:
l: 0cs: 26
reads: 13
aaaaaaaaaa
aaa
“rb”打开时:
l: 0cs: 26
reads: 26
dadadadada
dadadadada
dadada
可以看到区别了。
记得之前做文本解析时,就遇到过空文本里乱七八糟的字符的问题。
其中一个就是0x0d0a是windows下的换行符,而0x0a是linux下的。这两种模式的区别应该就是这个了。
附
查到的一些信息:
函数fopen是一个标准c函数,其功能是打开一个文件,之后便可以进行读或写的操作.其原型是这样的:FILE *fopen( const char *filename, const char *mode );
第一个参数是要打开文件的名字(路径),第二个参数是打开文件所用的模式.对于模式参数的”w”和”wb”,”r”和”rb”,我起初并不是很理解,按照课本上的说法,”w”是以文本的形式进行写入,而”wb”是以二进制模式进行写入.这样的解释令人感觉有点玄乎,不能准确理解.
最近写了个小程序,把数据以16进制的形式存到一个文件中,当从文件中读取时,发现读取的数据不对,进行调试时,发现读取的数据与写入文件中的数据发生了错位,进行调试发现写入时并没有错误,读取时,怎么就发生错位了呢?调试了半天发现每遇到0x0A,在它前面就会多一个0x0D.
那么,是什么原因造成的呢?几经周折之后,终于发现是fopen的参数引起的.如果这么写:fp = fopen(str,"wb");可以得到正常数据,而fp = fopen(str,"w");就得不到正常数据,遇到0x0A时,就会在其前面多一个0x0D.
原来,如果有参数b,是以二进制方式打开,这种方式不会进行”回车符”和”换行符”的转换.而如果没有b,即单以”w”为参数的话,系统就把换行符0A转换为0D0A,因为windows是以0D0A为换行符的.