C语言之文件操作


文件函数返回值

C


一、打开文件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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值