文章目录
文件函数返回值
一、打开文件fopen
1.函数原型:
FILE * fopen(const char * path,const char * mode);
返回值:打开文件成功返回一个文件指针,若打开文件失败则返回NULL
参数说明:
-
path:
字符串包含欲打开的文件路径及文件名(例如:D:\A.txt或D:/A.txt) -
mode:
代表着流形态,mode有下列几种形态字符串:- “w” : 写入内容到文件,不可以读文件。创建可写空白文件(如果文件不存在,则创建;如果文件存在则清空)
- “r” : 只可以读文件,不可以写文件。如果文件不存在则打开失败
- “a” : 追加,在文件末尾写入数据。
- “rb” : 二进制的方式读文件
- “wb” : 二进制的方式写文件
- “ab” : 二进制的方式追加
- “r+” : 可读可写。不存在则打开失败
- “w+” : 可读可写。创建可写空白文件(文件不存在则创建,文件存在则清空,对文件可读可写)
- “a+” : 可读可追写。
- 没有这个"rw": 不存在,不可以这样用
2.基本模板:
FILE* pFile = fopen("NewFile.txt", "w");
if (!pFile) //pFile==NULL
{
printf("打开失败\n");
}
例1:r+在原文件上替换内容
FILE *a = fopen("test.txt", "r+");
if (!a)
{
printf("error\n");
return 0;
}
fseek(a, 1, SEEK_SET);
fputs("hh",a);
fclose(a);
/*
原文件是abcd
现文件是ahhd
用新字符hh覆盖掉原字符bc
*/
例2:a 或 a+ 模式即总会在文件最尾添加内容,哪怕用 fseek() 移动了文件指针位置。
FILE *a = fopen("test.txt", "a+");
if (!a)
{
printf("error\n");
return 0;
}
rewind(a);
fputs("hh",a);
fclose(a);
/*
原文件是abcd
现文件是abcdhh
*/
二、关闭文件fclose
1.函数格式:
int fclose( FILE *fp );
返回值:当文件关闭成功时, 返回0, 否则返回一个非零值。
如:
fclose(fp); //不怎么使用返回值
注意:如果关闭一个打开失败的文件,那么系统会在运行时报错。
养成关闭文件的好习惯:在文件操作完成后我们应该调用该函数来关闭文件,如果不关闭文件将可能会丢失数据。因为在向文件写入数据时会先将数据输出到缓冲区,待缓冲区充满后才正式输出给文件。
2.刷新缓冲区fllush
向一个文件写入内容, 所写的内容将首先放在输出缓冲区中, 直到输出缓冲区存满或使用close()函数关闭文件时, 缓冲区的内容才会写入文件中。若无fclose() 函数, 则不会向文件中存入所写的内容或写入的文件内容不全。
格式:
int fflush(FILE *stream);
该函数将输出缓冲区的内容实际写入文件中, 而将输入缓冲区的内容清除掉。
三、文件的读
1.常用的函数
这些文件读取函数类似于读取控制台输入函数,很好理解,因此很常用。
(1)最常用的fscanf
int fscanf(FILE* stream , constchar* format , [argument]);
返回值为EOF(即-1), 表明读错误, 否则读数据成功。
如:a.txt中的内容是abc d,结果是abc,scanf读取字符串遇到空格结束了,这个和scanf()很像。
FILE *p = fopen("a.txt", "r");
char str[100] = "";
fscanf(p, "%s", str);
(2)fgetc()
作用:从文件指针指向的文件流中读取一个字符,读取一个字节后,光标位置后移一个字节
格式:
int fgetc(FILE *stream);
返回值:返回所读取的一个字节,如果读到文件末尾或者读取出错时返回EOF(一般值为-1)
如:
char ch=fgetc(fp);
(3)fgets()
格式:
char *fgets(char *buf, int bufsize, FILE *stream);
返回值:
函数成功将返回buf,失败或读到文件结尾返回NULL。因此我们不能直接通过fgets的返回值来判断函数是否是出错而终止的,应该借助feof函数或者ferror函数来判断。
作用:每次读取一行。
读取的数据保存在buf指向的字符数组中,每次最多读取bufsize-1个字符(第bufsize个字符赋’\0’),如果文件中的该行,不足bufsize个字符,则读完该行就结束。如若该行(包括最后一个换行符)的字符数超过bufsize-1,则fgets只返回一个不完整的行,但是,缓冲区总是以NULL字符结尾,对fgets的下一次调用会继续读该行。
PS:关于buf字符串数组的探究
char *str; //失败,没有初始化
fgets(str,7,fp);
char *str1;
str1 = (char*)malloc(sizeof(char) * 10); //成功
fgets(str,7,fp);
char str[10]; //成功
fgets(str,7,fp);
2.不常用的fread
size_t fread(
void *buffer, //用来存放数据的内存
size_t Size, //每一次读的大小
size_t Count, //读的次数
FILE * _File //文件指针
);
返回值:实际读取的次数的次数。
例1:
char readBuff[100]="";
fread(readBuff,10,4,fp);
例2:从文件中读100个整型数, 并把它们放到dat数组中
FILE *fp;
int dat[100];
fp = fopen("test_b.dat", "rb");/*打开一个二进制文件只读*/
if (fread(dat, sizeof(int), 100, fp) != 100)
{
if (feof(fp))
printf("End of file"); /*不到100个数文件结束*/
else
printf("Read error"); /*读数错误*/
fclose(fp); /*关闭文件*/
四、文件的写
1.常用的函数
这些文件读取函数类似于读取控制台输入函数,很好理解,因此很常用。
(1)最常用的fprintf
int fprintf (FILE* stream, const char* format, [argument]);如:
返回值:
为实际写入文件中的字罕个数(字节数)。如果写错误, 则返回一个负数
如:
FILE *p=fopen("nice.log","w");
char *str="abcd";
int a=4;
fprintf(p,"%s,%d",str,a);
fclose(p);
(2)fputc()
作用:将指定字符写到文件指针所指向的文件的当前写指针位置上
格式:
int fputc (char c, File *fp);
返回值:在正常调用情况下,函数返回写入文件的字符的ASCII码值,出错时,返回EOF
如:
fputc(ch,fp);
(3)fputs
作用:向指定的文件写入一个字符串(不自动写入字符串结束标记符‘\0’)
格式:
int fputs(char *str, FILE *fp);
返回值:若成功返回0,失败返回EOF
如:
fputs(str,fp);
printf("str = %s\n", str);
2.不常用的fwrite()
作用:向文件写入一个数据块
fwrite(
const void* buffer, //buffer是一个指针,对fwrite来说,是要获取数据的地址
size_t size, //一次写的大小
size_t count, //写的次数
FILE * stream //文件指针
);
返回值:实际写入的次数。
例1:
typedef struct
{
char name[10];
int num;
int age;
char addr[15];
}student;
void save()
{
FILE *fp;
int i;
if((fp=fopen("dat.txt","w"))==NULL)
{
printf("无法打开此文件!\n");
return;
}
for(i=0;i<SIZE;i++)
if(fwrite(&stu, sizeof(student), 1, fp) != 1)
printf("文件写入错误。!\n");
fclose(fp);
}
例2:把一个浮点数组写入文件
float f[6]={3.2, -4.34, 25.04, 0.1, 50.56, 80.5};
FILE *fp;
fp=fopen("test_b.dat", "wb"); /*创建一个二进制文件只写*/
fwrite(f, sizeof(float), 6, fp); /*将6个浮点数写入文件中*/
五、文件指针偏移:文件光标的移动
1.fseek()
int fseek
(
FILE * _File, //文件指针
long _Offset, //偏移量,偏移多少字节
int _Origin //偏移的起始位置
);
_Origin起始位置:
- SEEK_SET 0 文件开始位置
- SEEK_CUR 1 当前位置
- SEEK_END 2 文件末尾
如:偏移到文件尾:
fseek(p,0,SEEK_END)
2.rewind()
偏移到文件头:
rewind(FILE* fp);
文件末尾标志: EOF
3.feof()
格式:
int feof(FILE *stream);
返回值:当结尾时返回非零值,不是则返回0
如:
while(!feof(fp))
fgetc(ch,fp);
4.ftell()
告诉偏移位置:
long ftell(FILE* fp);
这个值是指示器从文件头开始算起的字节数, 返回的数为长整型数, 当返回-1时, 表明出现错误。
例:测算文件大小
fseek(fp, 0, SEEK_END);
int size = ftell(fp);
5.文件的读和写都与光标位置有关
例1:
文件内容
/*文件内容:
ok
yes
no
*/
FILE *fp = fopen("txt.txt", "r+");
fseek(fp, 9, SEEK_SET); //4+5
char str1[100];
fgets(str1,10,fp);
puts(str1); //no
分析:ok那一行中ok是2个字符,后面跟着隐形的换行符\n占1个字符,接着是这一行字符串结束的标志 '\0’占1个字符 ,一共4个字符。
六、例子:复制文件和合并文件
有一个文件叫a.txt 文件的内容是abcedd
,还有另外一个文件叫b.txt 文件的内容是111111
。
把他们合并后,变成c.txt,而c.txt中的内容是abcedd111111
。
1.fread()和fwrite()
(1)基本模板1:
FILE *pA=fopen("a.txt","r");
FILE *pB=fopen("b.txt","w");
char arr[100]="";
while(fread(arr,1,1,pA)) //当一个字符都读不到就结束
{
fwrite(arr,1,1,pB);
}
fclose(pA);
fclose(pB);
失败1:
FILE *a = fopen("a.txt", "w+");
FILE *b = fopen("b.txt", "w+");
FILE *c = fopen("c.txt", "w+");
...打开判断
fwrite("abcedd", sizeof("abcedd"), 1, a);
fwrite("111111", sizeof("111111"), 1, b);
char arr[100] = "";
while (fread(arr, 10, 10, a))
{
fwrite(arr, 10, 10, c);
}
while (fread(arr, 10, 10, b))
{
fwrite(arr, 10, 10, c);
}
...关闭文件
结果是:a.txt文件变成abcedd后面跟着一堆屯,b.txt也一样,c.txt全是一堆屯
原因:文件在光标在EOF处,出错。要加rewind();
失败2:
FILE *a = fopen("a.txt", "w+");
FILE *b = fopen("b.txt", "w+");
FILE *c = fopen("c.txt", "w+");
...打开判断
fwrite("abcedd", sizeof("abcedd"), 1, a);
fwrite("111111", sizeof("111111"), 1, b);
rewind(a);
rewind(b);
char arr[100] = "";
while (fread(arr, 10, 10, a))
{
fwrite(arr, 10, 10, c);
}
while (fread(arr, 10, 10, b))
{
fwrite(arr, 10, 10, c);
}
...关闭文件
结果:a.txt和b.txt正常,c.txt内容为空
原因:fread的返回值为0,一次读取的大小超过文件内容
失败3:
FILE *a = fopen("a.txt", "w+");
FILE *b = fopen("b.txt", "w+");
FILE *c = fopen("c.txt", "w+");
...打开判断
fwrite("abcedd", sizeof("abcedd"), 1, a);
fwrite("111111", sizeof("111111"), 1, b);
rewind(a);
rewind(b);
char arr[100] = "";
while (fread(arr, 1, 10, a))
{
fwrite(arr, 1, 10, c);
}
while (fread(arr, 1, 10, b))
{
fwrite(arr, 1, 10, c);
}
...关闭文件
结果:abcedd 111111 ,后面有空格
原因:fwrite写入的arr后面有空格
失败4:
FILE *a = fopen("a.txt", "w+");
FILE *b = fopen("b.txt", "w+");
FILE *c = fopen("c.txt", "w+");
...打开判断
fwrite("abcedd", sizeof("abcedd"), 1, a);
fwrite("111111", sizeof("111111"),1, b);
rewind(a);
rewind(b);
char arr[100] = "";
while (fread(arr, 1, 1, a))
{
fwrite(arr, 1, 1, c);
}
while (fread(arr, 1, 1, b))
{
fwrite(arr, 1, 1, c);
}
...关闭文件
结果:扡散摤ㄱㄱ1
原因:a.txt的EOF写入到了c中。需要在第二次写入时倒退一个字符。
具体实现1:
FILE *a = fopen("a.txt", "w+");
FILE *b = fopen("b.txt", "w+");
FILE *c = fopen("c.txt", "w+");
...打开判断
fwrite("abcedd", sizeof("abcedd"), 1, a);
fwrite("111111", sizeof("111111"), 1, b);
rewind(a);
rewind(b);
char arr[100] = "";
while (fread(arr, 1, 1, a))
{
fwrite(arr, 1, 1, c);
}
fseek(c, -1, SEEK_END);
while (fread(arr, 1, 1, b))
{
fwrite(arr, 1, 1, c);
}
...关闭文件
基本模板2
fseek(fp,0,SEEK_END);
int size=ftell(fp);
rewind(fp);
fread(arr,1,size,fp);
具体实现2:
FILE *a = fopen("a.txt", "w+");
FILE *b = fopen("b.txt", "w+");
FILE *c = fopen("c.txt", "w+");
fwrite("abcedd", sizeof("abcedd"), 1, a);
fwrite("111111", sizeof("111111"), 1, b);
int n_a = ftell(a);
int n_b=ftell(b);
rewind(a);
rewind(b);
char arr[100] = "";
fread(arr, 1, n_a,a);
fwrite(arr, 1, n_a, c);
fseek(c, -1, SEEK_END);
fread(arr, 1, n_b, b);
fwrite(arr, 1, n_b, c);
fcloseall();
2.按格式读取
1.0,2.1
#include <stdio.h>
int main()
{
FILE *p = fopen("C:\\Users\\sword\\Desktop\\a.txt", "r");
if (!p)
{
printf("error\n");
return 0;
}
float f[100];
int i = 0;
while(!feof(p))
{
fscanf(p, "%f,-=-=-", &f[i]);
i++;
}
printf("%f,%f,%f", f[0], f[1],f[2]);
return 0;
}