一直以来都奇怪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为换行符的.