31.0、C语言——文件操作 (2)

本文详细介绍了C语言中文件的打开、关闭、读写操作,包括fopen、fclose、fgetc、fputc、fgets、fputs、fscanf、fprintf、fwrite、fread等函数的使用,以及不同打开模式的含义。同时,文章还提到了标准输入输出流和结构体数据在文件操作中的应用。
摘要由CSDN通过智能技术生成

31.0、C语言——文件操作 (2)

1. 文件的打开和关闭:

        文件在读写之前应该先打开文件,在使用结束之后应该关闭文件;

        1. 在编写程序的时候,在打开文件的同时,都会返回一个 FILE* 指针变量指向该文件,也相当于建立了指针和文件的关系;

        2. ANSIC 规定使用 fopen() 函数来打开文件;fclose() 函数来关闭文件;

FILE* fopen ( const char* filename , const char* mode );
int fclose ( FILE* stream );

打开方式如下:

" r "(只读)为了输入数据,,打开一个已经存在的文本文件出错
" w "(只写)为了输出数据,打开一个文本文件建立一个新的文件
" a "(追加)向文本文件尾添加数据出错
" rb "(只读)为了输入数据,打开一个二进制文件出错
" wb "(只写)为了输出数据,打开一个二进制文件建立一个新的文件
" ab "(追加)向一个二进制文件尾添加数据出错
" r+ "(读写)为了读和写,打开一个文本文件出错
" w+ "(读写)为了读和写,建议一个新的文件建立一个新文件
" a+ "(只读)打开一个文件,在文件尾进行读写建立一个新的文件
" rb+ "(只读)为了读和写打开一个二进制文件出错
" wb+ "(只读)为了读和写,新建一个新的二进制文件建立一个新的文件
" ab+ "(只读)打开一个二进制文件,在文件尾进行读和写建立一个新文件

像以下代码,打开一个文件(只读) ->

        FILE* pf = fopen( " test.txt ", " r " );

        如果打开成功,则会创建一个 FILE 类型的结构体去管理维护这个打开的文件,然后返回一个指向这块存放文件信息 FILE 结构体内存的指针,如果打开失败则会返回一个 NULL 空指针;

那么打开成功,读取文件之后,我们要主动的关闭文件 ->

        fclose( pf );
        pf = NULL;

2. 读写文件:

        1. 我们可以发现,如果只是 ( 读文件 ) ,打开的时候如果该文件不存在就直接报错;但是如果是 ( 写文件 ) 打开文件,发现文件不存在,则新建一个该文件【其实如果是写的话不管文件是否存在都会去新建一个同名的文件】;

        2. 除非是给文件追加内存,否则其他任何改写文件的方式都是新建一个同名文件,然后将原来的文件销毁掉【也就是说只要是改写文件,原来文件的内容就会被销毁,然后新建一个同名的文件】;

文件的顺序读写:

功能函数名适用于
字符输入函数fgetc所有输入流
字符输出函数fputc所有输出流
文本行输入函数fgets所有输入流
文本行输出函数fputs所有输出流
格式化输入函数fscanf所有输入流
格式化输出函数fprintf所有输出流
二进制输入fread文件
二进制输出fwrite文件

上述函数的 剖析 与 使用 ->

1. fgetc ( ) 函数 

        fgetc ( FILE* stream ); //一次读取一个字符;

2. fputc ( ) 函数   

        fputc ( FILE* stream , char ch ); //一次写一个字符;

3. fgets ( ) 函数  

        fgets ( char* string , int n , FILE* stream ); //读取出来的字符放到string中去,最多可以读n个字符,从stream中读取数据;

4. fputs ( ) 函数

        int fputs ( const char* string , FILE* stream ); //将要写的字符串内容放到 string 中,然后通过 stream 流写到文件中去;

        5. 从键盘标准输入流中读取数据->

int main() {
    char buf[1024] = {0};
    fgets (buf , 1024 , stdin); // stdin就是从标准输入读取
    fputs (buf , stdout); // stdout 就是标准输出,写到屏幕中去
    // 那么等价于以下这种写法
    // gets ( buf );
    // puts ( buf );
    return 0;
}

6. printf、scanf 函数

        printf、scanf 默认输出标准输出流和标准输入流,所以不需要指定流;
        而 fprintf 需要我们指定一个输出流【注意这里是将 内 容 写 入 文 件 】->
        而 fscanf 需要我们指定一个输入流【注意这里是将文件内容读入程序】->

struct S {
    int n;
    float score;
    char arr[10];
};

int main() {
    struct S s = { 100 , 3.14f , "bit" };
    FILE* pf = fopen("test.txt","w");
    if(pf == NULL) {
        printf("%s" , strerror(errno));
        return 0;
    }
    // 格式化的形式写文件
    fprintf(pf , "%d %f %s" , s.n,s.score,s.arr);
    // 格式化的形式读文件也一样
    // fscanf(pf , "%d %f %s" , &(s.n),&(s.score),s.arr);
    fclose(pf);
    pf = NULL;
    return 0;
}

7. fwrite ( ) 函数

size_t fwrite ( const void* buffer , size_t size , size_t count , FILE* stream );

        第一个参数 buffer 指的是 -> 要写进去的数据的地址;

        第二个参数 size 指的是 -> 你要写一个元素,这个元素有多大(单位是字节);

        第三个参数 count 指的是 -> 要写多少个这样大小的元素;

        第四个参数 stream 指的是 -> 写到哪个文件去,也就是流;

下面给大家举个实例 ->

struct S {
	char name[30];
	int age;
	double score;
};

int main() {
	struct S s = {"澜色海湾",18,100};
	FILE* pf = fopen("TEST.txt", "wb");
	if (pf == NULL) {
		return 0;
	}
	fwrite(&s,sizeof(struct S),1,pf);
	fclose(pf);
	pf = NULL;
	return 0;
}

        上述这段代码将 结构体对象s中的数据存到了 TEST.txt 文本文件中,如下所示->

        可以看到该结构体数据是以 二进制的形式去存储到 TEST.txt 文本文件中的;有些是乱码,有些是原数据;

8. fread ( ) 函数

size_t fread ( const void* buffer , size_t size , size_t count , FILE* stream );

        参数的意义和上面 fwrite() 函数如出一辙就不过多介绍了,这里主要说一下 返回的 size_t 指的是函数真实读到数据的个数;

        直接上实例代码,将刚刚以二进制形式存储进TEST.txt文件里去的结构体数据,以二进制的形式读取出来,然后将正常的格式打印出来 ->

struct S {
	char name[30];
	int age;
	double score;
};
int main() {
	struct S tmp = { 0 };
	FILE* pf = fopen("TEST.txt", "rb");
	if (pf == NULL) {
		return 0;
	}
	//二进制的形式读文件
	fread(&tmp, sizeof(struct S), 1, pf);
	printf("%s %d %lf\n",tmp.name,tmp.age,tmp.score);
	fclose(pf);
	pf = NULL;
	return 0;
}

输出结果如下所示 ->

来看一组函数的对比【这是一道面试题】->

scanf / fscanf / sscanf

printf/ fprintf / sprintf

        1. scanf / printf 是针对标准输入 / 输出流的格式化输入 / 输出语句;

        2. fscanf / fprintf 是针对所有输入 / 输出流的,格式化输入 / 输出语句;

        3.sscanf / sprintf -> sscanf 是从字符串中读取格式化的数据;
                                   -> sprintf 是吧格式化数据输出成字符串;

那么给大家解释一下 sscanf 和 sprintf 函数的用法 ->

struct S {
    int n;
    float score;
    char arr[10];
};
int main() {
    struct S s = { 100 , 3.14f , "abcdef" };
    char buf[1024] = {0};
    sprintf( buf , "%d %f %s" , s.n , s.score , s.arr );
    printf("%s",buf);
    return 0;
}

        那么这里打印出来的结果是 100 3.140000 abcdef ,相当于将这些数据全部转化为 字符串类型 的数据了;        

        也就是说 sprintf 函数有能力将一个结构体的对象中的 数据 转换成一个 字符串;

         既然能够转换成字符串,当然也有能力将转换成字符串的结构体对象数据,还原回原来的数据类型 -> 

struct S {
    int n;
    float score;
    char arr[10];
};
int main() {
    struct S s = { 100 , 3.14f , "abcdef" };
    struct S tmp = { 0 };
    char buf[1024] = { 0 };
    //把格式化的数据转换成字符串存储到 buf
    sprintf( buf , "%d %f %s" , s.n , s.score , s.arr );
    //从 buf 中读取格式化的数据到 tmp 中
    sscanf( buf , "%d %f %s" , &(tmp.n) , &(tmp.n) , tmp.arr );
    return 0;
}

读写打开的文件——代码实例 ->

        1. 以写 的 方式打开 TEST.txt 文件【这里 pfWrite 其实也就是输出流~;最后也是将这个输出流关闭】;

然后写入   'h'  'k'  'l'   三个字符到 TEST.txt 文件之中 ->

int main() {
	FILE* pfWrite = fopen("TEST.txt","w");
	if (pfWrite == NULL) {
		printf("%s\n",strerror(errno));
		return 0;
	}
	//写文件
	fputc('h',pfWrite);
	fputc('k', pfWrite);
	fputc('l', pfWrite);
	//关闭文件
	fclose(pfWrite);
	pfWrite = NULL;
	return 0;
}

 执完程序后,打开文件TEST.txt发现修改成功,内容为 hkl ;

        2. 再来以读的方式打开 TEST.txt 文件【这里 pr 其实也就是输入流~;最后也是将这个输入流关闭】;

然后读取文件中的内容;

int main() {
	FILE* pr = fopen("TEST.txt","r");
	if (pr == NULL) {
		printf("%s\n",strerror(errno));
		return 0;
	}
    //从TEST.txt文件中读取内容
	printf("%c", fgetc(pr));
	printf("%c", fgetc(pr));
	printf("%c", fgetc(pr));
	//关闭文件
	fclose(pr);
	pr = NULL;
	return 0;
}

执行程序后,成功打印出了 h k l 三个字符;

3. 输出流和输入流:

        1. 那我们的 屏幕 和 键盘 也是一种 输出流 和 输入流;

        2. 屏幕是标准输出设备 - stdout,键盘是标准输入设备 - stdin,这两个流设备是程序一旦执行就默认打开的两个流设备;

        3. 我们可以发现当scanf() 输入 和 printf() 输出的时候,并不需要打开流关闭流就可以正常使用,正是因为他是默认打开的;

三个默认流:

        1. stdin    FILE*
        2. stdout  FILE*
        3. stderr   FILE*

        下面这段代码,没有用到scanf 和 printf,而是用了键盘标准输入流 stdin,和屏幕标准输出流 stdout,执行程序后仍然能够实现键盘输入一个值然后将这个值输出出来;

int main() {
	int ch = fgetc(stdin);
	fputc(ch, stdout);
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值