文件操作:fgets与gets区别+fread/fwrite +流定位接口
一、fgets和gets的区别
1.fgets
- 从指定的已打开文件中读取最多一行数据,遇到\n停止读取。
- fgets会读取一个换行,并在末尾自动加一个'\0'。
- fgets最多读取size - 1个字符,最后一个位置存放\0。
- 取掉fgets的\n换行。eg:s[strlen(s) - 1] = '\0';
2.gets
- 从指定终端设备读取数据。
- gets会将终端读到的\n字符替换成\0。
- gets是危险的,因为在读取时,没有大小的限制,可能会造成内存越界。
二、二进制流的输入输出
1.size_t fwrite(const void *ptr,size_t size,size_t nmemb,FILE *stream)
(1)结构说明
- 功能:向文件写入nmemb个大小为size的数据到文件中。
- 参数:ptr-要写入的数据的首地址
size-每个元素的字节数
nmemb-要写入的元素个数
stream-要写入的文件流指针
- 返回值:成功:返回实际写入元素个数
(2)示例程序
#include<stdio.h>struct stu
{int id;char name[32];int score;
}; //定义结构体int main(int argc,const char argv[])
{FILE *fp = fopen("1.txt","w"); //打开文件if(NULL == fp){printf("fopen erro");return -1;} //判断是否成功打开文件struct stu s[5] = {{1,"zhangsan",99},{2,"lisi",88},{3,"wanger",66},{4,"maliu",77},{5,"zhaowu",100}};size_t cnt = fwrite(&s,sizeof(struct stu),3,fp);printf("cnt = %ld\n",cnt);fclose(fp);return 0;
}
2.size_t fread(void *ptr,size_t size,size_t nmemb,FILE *stream)
(1)结构说明
- 功能:向文件中读取nmemb个大小为size的元素。
- 参数:ptr-存储读取到数据的首地址
size-每个元素的字节数
nmemb-希望从文件中读取的元素个数
stream-要读取的文件的文件流指针
- 返回值:成功:返回实际读取的元素个数
读到文件末尾:0
(2)示例程序
#include<stdio.h>
struct stu
{int id;char name[32];int score;
};int main(int argc, const char argv[])
{FILE *fp = fopen("1.txt","r");if(NULL == fp){printf("fopen erro");return -1;}struct stu s[10];size_t cnt = fread(s,sizeof(struct stu),5,fp);for(int i = 0;i < cnt; ++i){printf("%d %s %d\n",s[i].id,s[i].name,s[i].score);}fclose(fp);return 0;
}
三、流定位相关接口
1.fseek-----int fseek(FILE *stream,long offset,int whence)
- 功能:实现文件流重新定位
- 参数:stream--需要定位的文件流指针
offset--偏移量
whence--定位的相对位置➡SEEK_SET:从头进行偏移
➡SEEK_CUR:从当前位置进行偏移
➡SEEK_END:从末尾进行偏移
- 返回值:成功:返回当前的偏移量
失败:-1
- 示例程序:
#include <stdio.h>int main(int argc, const char *argv[])
{FILE *fp = fopen("./1.txt", "w");if (NULL == fp){printf("fopen error\n");return -1;}fseek(fp, 10, SEEK_SET);fputc('A', fp);long offset = ftell(fp);printf("offset = %ld\n", offset);fseek(fp, 5, SEEK_CUR);fputc('B', fp);offset = ftell(fp);printf("offset = %ld\n", offset);fseek(fp, -2, SEEK_CUR);fputc('C', fp);fseek(fp, 4, SEEK_END);fputc('D', fp);fseek(fp, -10, SEEK_END);fputc('E', fp);fclose(fp);return 0;
}
通过运行程序可知,其偏移量可正可负。
2.ftell -- long ftell(FILE *stream)
- 功能:获取流的当前位置到文件开头的偏移量
- 参数:stream--需要定位的文件流指针
- 返回值:偏移量:byte
3.rewind--void rewind(FILE *stream)
- 功能:流复位函数(复位到开头)
4.应用
- 获取文件的大小(字节数)
fseek(fpsrc, 0, SEEK_END);
long len = ftell(fpsrc);
rewind(fpsrc); //文件流指针复位
#include<stdio.h>
int main(int argc,const char *argv[])
{FILE *fp = fopen("fread.c","r");if(NULL == fp){printf("fopen error\n");return -1;}fseek(fp,0,SEEK_END);long offset = ftell(fp);offset = ftell(fp);printf("offset = %ld\n",offset);fclose(fp);return 0;
}
- 产生一个空洞文件➡抢占磁盘空间(结束后必须复位)
fseek(fpdst, len-1, SEEK_SET);
int ret = fputc('\0', fpdst);
if (EOF == ret)
{
printf("磁盘空间不足\n");
return -1;
}rewind(fp); //复位
4.综合程序示例
程序实现的功能:
示例程序:
#include <stdio.h>
#include <stdlib.h>int main(int argc, const char *argv[])
{if (argc < 3){printf("Usage : ./a.out <srcfile> <dstfile>\n");return -1;}FILE *fpsrc = fopen(argv[1], "r");if (NULL == fpsrc){printf("fopen error srcfile\n");return -1;}//1、 获取源文件大小fseek(fpsrc, 0, SEEK_END);long len = ftell(fpsrc);rewind(fpsrc);//2、抢占目标文件的磁盘空间FILE *fpdst = fopen(argv[2], "w");if (NULL == fpdst){printf("fopen error dstfile\n");return -1;}fseek(fpdst, len-1, SEEK_SET);int ret = fputc('\0', fpdst);if (EOF == ret){printf("磁盘空间不足\n");fclose(fpsrc);fclose(fpdst);return -1;}rewind(fpdst); //3、数据拷贝char buff[1024] = {0};while (1){size_t cnt = fread(buff, 1, sizeof(buff), fpsrc);if (0 == cnt){break;}fwrite(buff, 1, cnt, fpdst);}fclose(fpsrc);fclose(fpdst);return 0;
}