fseek写文件
FAQ
从串口或者网络接收文件,文件分包带序号,一开始用ab+
的形式,发现如果中间丢失了一包数据之后,fseek
不会跳过这个区域,直接在尾巴追加,遂仔细翻看APUE
,以及编写测试代码
API相关
FILE *fopen(const char *restrict pathname, const char *restrict mode);
// SEEK_SET 文件头的偏移
int fseek(FILE *stream, long offset, int whence);
long ftell(FILE *stream);
void rewind(FILE *stream);
int fgetpos(FILE *restrict stream, fpos_t *restrict pos);
int fsetpos(FILE *stream, const fpos_t *pos);
文件读写模式
r 可读
w 可写
+ 允许读写,具有下列限制:
如果中间没有fflush、fseek、fsetpos或rewind,则在输出的后面不能直接跟随输入。
如果中间没有fseek、fsetpos或rewind,或者一个输出操作没有到达文件尾端,则在输入操作之后不能直接跟随输出
b 二进制,在linux没区别,win上有用
a 追加形式,只允许在尾巴写
模式配合seek
- 使用带
a
的选项,只能追加在尾巴,即使fseek
超出文件尾,也只是在EOF的位置追加 - 使用
rb+/wb
的形式,fseek
可以留空写,但是w
会提前清空文件 - 使用
rb+
,可以实现fseek
到指定位置来读写 fseek
只能用替换,不能实现插入功能
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
// 测试ab+ 的seek 的功能
void wa(unsigned char * mode,int addr,char val )
{
FILE* fp = fopen("info",mode);
if(fp== 0)
{
printf("wa ERROR mode=%s\r\n",mode);
return ;
}
int f_ret=fseek(fp,addr,SEEK_SET);
if(f_ret!=0)
{
printf("fseek ERROR mode=%s\r\n",mode);
return ;
}
f_ret=fwrite(&val,sizeof(val),1,fp);
if(f_ret!=1)
{
printf("wa write File Error mode=%s \r\n",mode);
return;
}
fclose(fp);
printf("write File mode=%s,@%d,=%c\r\n",mode,addr,val);
printf("hexdump -C info\r\n");
system("hexdump -C info");
}
void Init()
{
FILE* fp = fopen("info","w+");
if(fp!= 0)
{
char initBuf[]="0123456789";
int f_ret=fwrite(initBuf,sizeof(initBuf),1,fp);
if(f_ret!=1)
{
printf("Init File Error\r\n");
return ;
}
fclose(fp);
}
printf("Init File Success\r\n");
printf("hexdump -C info\r\n");
system("hexdump -C info");
}
int main ()
{
printf("\r\n\r\n\r\n\r\n\r\n#############Test fopen###########\r\n\r\n\r\n");
Init();
printf("// ab+ 即使fssek 到中间位置,也是在尾巴写入\r\n");
wa("ab+",2,'A');
Init();
printf("// ab+ 即使fssek 抄出文件尾巴,也是在尾巴写入,不会留空\r\n");
wa("ab+",100,'A');
Init();
printf("// rb+ fssek 到中间,是走文字替换\r\n");
wa("rb+",2,'A');
Init();
printf("// rb+ fssek 超出文件,会留空追加\r\n");
wa("rb+",100,'A');
Init();
printf("// wb+ fssek 超出文件,会留空追加, 提前都会清空文件\r\n");
wa("wb+",100,'A');
printf("// wb fssek 超出文件,会留空追加, 提前都会清空文件\r\n");
Init();
// wb 是不能读的
//wa("wb",100,'A');
return(0);
}