求助:以rb+打开文件,读取到文件结尾,开始写文件,则写文件失败,不知道为什么

雪琦 2012-08-11 08:55:11
以下是源码

本意是想打开一个二进制文件,在其尾部加入一些特定信息如程序名称 版本号 校验值等
但是每次写文件都会返回失败,不知道为什么,获取的错误码是32

请各位帮忙分析分析,原因是什么,在此谢过了

//返回值 0:失败 1:成功
int fill_bin_file(char *filename,unsigned char file_data,long size)
{
FILE *fp;
long cur_size;
unsigned char val;
int j;

//============打开文件
fp = fopen(filename,"rb+");
if (fp == NULL)
{
printf("open file fail\n");
return 0;
}
//==========获取文件的当前长度
if (fseek(fp,0,SEEK_END)!=0)
{
printf("seek file fail\n");
fclose(fp);
return 0;
}
cur_size = ftell(fp);
//==========校验文件长度
if ((cur_size == -1)||(cur_size+32 >= size))
{
printf("get file size fail\n");
fclose(fp);
return 0;
}
printf("file current size is : %u\n",cur_size);
//=========计算从文件开始到当前位置的异或校验
crc_val = 0;
j=0;
if (fseek(fp,0,SEEK_SET)!=0)
{
printf("seek file fail\n");
fclose(fp);
return 0;
}
while(j<cur_size)
{
if (fread(&val,1,1,fp)!=1)
{
printf("read file error\n");
fclose(fp);
return 0;
}
crc_val ^= val;
j++;
}
//===========填充文件
while (cur_size < size-32)
{
if(fwrite(&file_data,1,1,fp)!=1)
{
printf("write file fail\n");
fclose(fp);
return 0;
}
cur_size++;
crc_val ^= file_data;
}
//==========填写后缀信息
//填写程序名
for (j=0;j<10;j++)
{
fwrite(&dev_type[j],1,1,fp);
cur_size++;
crc_val ^= dev_type[j];
}
//填写版本
for (j=0;j<10;j++)
{
fwrite(&version[j],1,1,fp);
cur_size++;
crc_val ^= version[j];
}
//填写保留
for (j=0;j<11;j++)
{
fwrite(&file_data,1,1,fp);
cur_size++;
crc_val ^= file_data;
}
//填写校验
fwrite(&crc_val,1,1,fp);
fclose(fp);
return 1;
}
...全文
204 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
00000_00 2015-01-08
  • 打赏
  • 举报
回复
引用 7 楼 qq120848369 的回复:
[Quote=引用 5 楼 的回复:] 1楼可行 谢谢了 不过为什么必须加呢 fread的时候指针不是自己会后移吗? [/Quote] 要想知道为什么,你得知道Linux C的API和C stdio的关系。 fread 1字节,其实可能是read 10字节,返回给用户1字节。 fwrite 10字节, 其实可能write 0字节,缓存了10字节。 而C std io在实现的时候就那么制定的,它认为用户要么一直写,要么一直读,所以它假想用户不会在同一个FILE上进行读写切换而不在中间进行转化。 所以你要是违背它的实现意图做事情, 必然会引起一些缓存参数的错误解释, 造成无法预估的结果。 如果之前处于写状态,那么fseek首先write写出缓冲区,之后lseek偏移到指定文件位置。 如果之前处于读状态,那么fseek直接抛弃缓冲区所有数据,然后lseek。 如果你在读与写之间没有fseek,那么对不起,C标准IO库是不care你的,说不定将写缓存当作读缓存,将读缓存当作写缓存。
厉害,厉害!!
雪琦 2012-08-11
  • 打赏
  • 举报
回复
有点明白了 多谢了
qq120848369 2012-08-11
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 的回复:]

1楼可行 谢谢了 不过为什么必须加呢 fread的时候指针不是自己会后移吗?
[/Quote]

要想知道为什么,你得知道Linux C的API和C stdio的关系。

fread 1字节,其实可能是read 10字节,返回给用户1字节。
fwrite 10字节, 其实可能write 0字节,缓存了10字节。

而C std io在实现的时候就那么制定的,它认为用户要么一直写,要么一直读,所以它假想用户不会在同一个FILE上进行读写切换而不在中间进行转化。 所以你要是违背它的实现意图做事情, 必然会引起一些缓存参数的错误解释, 造成无法预估的结果。

如果之前处于写状态,那么fseek首先write写出缓冲区,之后lseek偏移到指定文件位置。
如果之前处于读状态,那么fseek直接抛弃缓冲区所有数据,然后lseek。

如果你在读与写之间没有fseek,那么对不起,C标准IO库是不care你的,说不定将写缓存当作读缓存,将读缓存当作写缓存。
雪琦 2012-08-11
  • 打赏
  • 举报
回复
看过几本教材,可能自己粗心,确实想不起来哪本上说过切换时要fseek下 该好好补补了
雪琦 2012-08-11
  • 打赏
  • 举报
回复
1楼可行 谢谢了 不过为什么必须加呢 fread的时候指针不是自己会后移吗?
taodm 2012-08-11
  • 打赏
  • 举报
回复
楼主,换本合格的教材吧。
文件读写转换的时候要fseek一下都没讲的教材直接扔掉。
另外,要清除FILE的错误状态,具体函数自己查c库手册。
雪琦 2012-08-11
  • 打赏
  • 举报
回复
这个确实可以,不过校验值是对整个文件进行的,所以我得读取现有的数据计算校验值.
读数据时如果没读到文件结尾,则可以写入,但是一到写入的数据超过现有长度,就写入失败,不是应该自动追加吗?
漫步者、 2012-08-11
  • 打赏
  • 举报
回复
你在尾部直接添加就行了,打开方式为ab+;
qq120848369 2012-08-11
  • 打赏
  • 举报
回复

fseek(fp, 0, SEEK_END);
//===========填充文件
while (cur_size < size-32)
{
if(fwrite(&file_data,1,1,fp)!=1)
{
printf("write file fail\n");
fclose(fp);
return 0;
}
cur_size++;
crc_val ^= file_data;
}

69,373

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧