文件的操作

文件操作

C语言输入输出的对象,主要就是标准输出流(stdout)与标准输入流(stdin)。所谓标准输出流通俗地说就是屏幕输出,标准输入流就是键盘输入。除了这两种之外,C语言还可以对磁盘文件和外部设备输入输出,这就用到了文件读写函数。

1、文件的打开关闭

FILE是系统使用typedef定义出来的有关文件信息的一种结构体类型,结构中含有文件名、文件状态和文件当前位置等信息。

声明FILE结构体类型的信息包含在头文件“stdio.h”中,一般设置一个指向FILE类型变量的指针变量,然后通过它来引用这些FILE类型变量。通过文件指针就可对它所指的文件进行各种操作。

fopen函数

1、功能:打开文件

2、函数格式:

#include <stdio.h>
FILE* fopen(const char* filename, const char* mode);

3、函数参数:

filename:需要打开的文件名,根据需要加上路径

mode:打开文件的模式设置

4、函数返回值:

成功:文件指针

失败:NULL

fclose函数

1、功能:关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。

2、函数格式:

#include <stdio.h>
int fclose(FILE* stream);

3、函数参数:

stream:文件指针

4、函数返回值:

成功:0

失败:-1

5、fclose函数注意点:

  • 打开的文件会占用内存资源,如果总是打开不关闭,会消耗很多内存

  • 一个进程同时打开的文件数是有限制的,超过最大同时打开文件数,再次调用fopen打开文件会失败

  • 如果没有明确的调用fclose关闭打开的文件,那么程序在退出的时候,操作系统会统一关闭。

2、文件的打开与关闭代码实现

#define _CRT_SECURE_NO_WANINGS
#include <stdio.h>
// 1. 文件打开关闭
void test01(){
    // r 以只读方式打开一个文本文件(不创建文件,若文件不存在则报错)
    // 下面写法不推荐
    // fopen("C:\\Users\\cpp\\Documents\\codes\\day12\\day12\\demo1.txt", "r");
    // 大部分系统都支持下面的路径写法(绝对路径)
    // fopen("C:/Users/cpp/Documents/codes/day12/day12/demo1.txt", "r");
    // 相对路径
    FILE* fp = fopen("./demo1.txt", "r");
    // 返回的 FILE 指针,指向了一块内存,这块内存就存储了当前打开文件的信息
    // FILE 指针指向的空间是由系统帮我们申请的
    // 文件打开失败,返回 NULL
    if (NULL == fp){
        printf("文件打开失败!\n");
        return;
    }
    // 关闭文件
    // 如果打开文件没有关闭,当程序结束的时候,文件也被关闭。
    // 文件使用完毕,要及时释放。
    // 1. fp 指向的内存就会被释放.
    // 2. 刷新缓冲区,会将缓冲区中的文件内容写入到磁盘中
    // 3. 对于程序,可打开的文件数量有上限的。
    fclose(fp);
    fp = NULL;
}
int main(){
    test01();
	return 0;
}

3、文件打开模式

打开模式欲操作的文件不存在成功打开之后的指针位置是否清空原先内容
r打开失败开头
w新建开头
a新建结尾
r+打开失败开头
w+新建开头
a+新建结尾

4、文件字符读写

  • 单个字符输入输出函数:fgetchar与fputchar(或者getc与putc);

  • 单行字符串输入输出函数:fgets与fputs;

  • 格式化输入输出函数:fscanf与fprintf;

Ⅰ、文件字符 写 fputc 函数

1.函数格式: #include <stdio.h>

int fputc(int ch, FILE* stream);

2.函数功能: 将ch转换为unsigned char后写入stream指定的文件中

3.函数参数: ch:需要写入文件的字符

stream:文件指针

4.函数返回值:成功:成功写入文件的字符

失败:返回-1

Ⅱ、文件字符 读 fgetc函数

1.函数格式:#include <stdio.h>

int fgetc(FILE* stream);

2.函数功能:从stream指定的文件中读取一个字符

3.函数参数:stream:文件指针

4.函数返回值:成功:返回读取到的字符

失败:-1

5、测试文件的写操作

#define _CRT_SECURE_NO_WANINGS
#pragma warning(disable : 4996)
#include <stdio.h>
#include <stdio.h>
int main(){
	char s[80]="\0";
	FILE* pf = fopen("./小柯南.txt", "w");
	puts("请输入一行文字:");	//fputs("请输入一行文字:", stdout);
	scanf_s("%s", s,sizeof(s));				//fgets(s, sizeof(s), stdin);
	fputs(s, pf);
	fclose(pf);
	return 0;
}

6、测试文件的读操作

#define _CRT_SECURE_NO_WANINGS
#pragma warning(disable : 4996)
int main(){
	int c;
	FILE* pf = fopen("./小柯南.txt", "r");
	if (!pf)
	{
		puts("打开文件失败!");
		return -1;
	}
	while (1){
		c = getc(pf);
		if (c == -1)
			break;
		if (c == '\r')
			continue;
		putchar(c); 		//putc(c,stdout);
	}
	fclose(pf);
	return 0;
}
//linux文本文件的换行符是:\n
//windows文本文件的换行符是:\r\n

7、判断文件结束(EOF、feof函数)、实现文件拷贝

Ⅰ、EOF函数

在C语言中,EOF表示文件结束符(end of file)。在while循环中以EOF作为文件结束标志,这种以EOF作为文件结束标志的文件,必须是文本文件。在文本文件中,数据都是以字符的ASCII代码值的形式存放。我们知道,ASCII代码值的范围是0~127,不可能出现-1,因此可以用EOF作为文件结束标志。

函数格式:

#define EOF   (-1)

Ⅱ、feof 函数

当把数据以二进制形式存放到文件中时,就会有-1值的出现,因此不能采用EOF作为二进制文件的结束标志。为解决这一个问题,ANSI C提供一个feof函数,用来判断文件是否结束。feof函数既可用以判断二进制文件又可用以判断文本文件。

函数格式:

#include <stdio.h>
int feof(FILE* stream);

函数功能:

检测是否读取到了文件结尾。判断的是最后一次“读操作的内容”,不是当前位置内容。

函数参数:

  • stream:文件指针

函数返回值:

  • 非0值:已经到文件结尾

  • 0:没有到文件结尾

8、判断文件结束

#define _CRT_SECURE_NO_WANINGS
#pragma warning(disable : 4996)
#include <stdio.h>
// 1. 文件打开关闭
void test01() {
	//1.打开文件
	FILE* fp = fopen("./demo.txt", "r");
	if (NULL == fp) {
		printf("文件打开失败!\n");
		return;
	}
	// 2. 读取文件内容
	char ch = 0;
	// "abc[-1]"
	while (1) {
		ch = fgetc(fp);
		// 如果 feof 函数返回 true, 表示文件结束
		if (feof(fp))
		{
			break;
		}
		printf("%c", ch);
	}
	// 文件关闭
	fclose(fp);
	fp = NULL;
}
int main() {
	test01();
	return 0;
}

9、实现文件拷贝

#define _CRT_SECURE_NO_WANINGS
#pragma warning(disable : 4996)
#pragma warning(disable : 6031)
#include <stdio.h>
#include <stdio.h>
/*实现思路:
1. 输入待拷贝的文件路径.
2. 输入拷贝的目的地路径.
3. 打开两个文件 :
	1. 待拷贝文件 : 以读的方式打开
	2. 目的地文件 : 以写的方式打开
	4. 文件拷贝
	1. 从待拷贝文件中读取一个字符
	2. 将该字符写入到目的地文件
	5. 关闭两个文件。
	```c
	*/
	void test(){
	// 1. 获得文件路径
	char file_src[128] = { 0 };
	char file_dst[128] = { 0 };
	printf("请输入待拷贝文件路径:");
	scanf("%s", file_src);
	//fflush(file_src);
	printf("请输入目的地文件路径:");
	scanf("%s", file_dst);
	// 2. 打开文件
	FILE* fp_read = fopen(file_src, "r");
	if (NULL == fp_read){
		printf("文件: %s 打开失败!\n", file_src);
		return;
	}
	FILE* fp_write = fopen(file_dst, "w");
	if (NULL == fp_write){
		// 关闭前面打开的文件
		fclose(fp_read);
		fp_read = NULL;
		printf("文件: %s 打开失败!\n", file_dst);
		return;
	}
	// 3. 拷贝实现
	char ch = 0;
	// 从待拷贝文件中读取内容
	while ((ch = fgetc(fp_read)) != EOF)
	{
		// 将读取的内容写入到目的地文件中
		fputc(ch, fp_write);
	}
	// 4. 关闭文件
	fclose(fp_read);
	fp_read = NULL;
	fclose(fp_write);
	fp_write = NULL;
	printf("%s 拷贝到 %s 成功!\n", file_src, file_dst);
}
	int main() {
		test();
		return  0;
	}

10、行文件读写

Ⅰ、fputs函数

函数格式:

#include <stdio.h>
int fputs(const char* str, FILE* stream);

函数功能:

将str所指定的字符串写入到stream指定的文件中,字符串结束符 ‘\0’ 不写入文件。

函数参数:

  • str:字符串
  • stream:文件指针

函数返回值:

  • 成功:0

  • 失败:-1

Ⅱ、fgets函数

函数格式:

#include <stdio.h>
char* fgets(char* str, int size, FILE* stream);

函数功能:

从stream指定的文件内读入字符,保存到str所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了size - 1个字符为止,最后会自动加上字符 ‘\0’ 作为字符串结束。

函数参数:

  • str:字符串

  • size:指定最大读取字符串的长度(size - 1)

  • stream:文件指针

函数返回值:

  • 成功:成功读取的字符串

  • 读到文件尾或出错: NULL

11、行文件写读案例

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<string.h>
#include<stdlib.h>
// 1. 把内容写入到文件中
void test01(){
    // 1. 打开文件
    FILE* fp = fopen("./小柯南.txt", "w");
    if (NULL == fp)
    {
        return;
    }
    // 2. 写文件
#if 0
    char* s = "hello world";
    // 从 s 字符串第一个字符开始到 \0 之前的内容写入到文件中
    fputs(s, fp);
#endif
    // 字符串指针数组
    char* name[] = { "conan\n", "sim\n", "deral\n", "Browers\n", "cliner\n", "pitcher\n" };
    for (int i = 0; i < sizeof(name) / sizeof(name[0]); ++i)
    {
        fputs(name[i], fp);
    }
    // 3. 关闭文件
    fclose(fp);
    fp = NULL;
}
// 2. 从文件中读取出来
void test02(){
    // 1. 打开文件
    FILE* fp = fopen("./小柯南.txt", "r");
    if (NULL == fp)
    {
        return;
    }
    // 2. 读文件
    while (1)
    {
        // 申请空间,用于存储文件内容
        char line[128] = { 0 };
        // 从文件中一次读取一行
        fgets(line, 128, fp);
        // 判断文件是否结束
        if (feof(fp))
        {
            break;
        }
        // 打印文件内容
        printf("%s", line);

    }
    // 3. 关闭文件
    fclose(fp);
    fp = NULL;
}
int main() {
    test01();
    test02();
    return 0;
}

12、文件输入输出函数等价关系

  • 1.单个字符输入输出函数:
getchar()fgetchar(stdin)以及getc(stdin)三者是等价的;

putchar(c)fputchar(c, stdout)以及putc(c,stdout)三者是等价的;
  • 2.单行字符串输入输出函数:
gets(s)fgets(s,sizeof(s),stdin)两者是等价的;
puts(s)fputs(s,stdout)两者是等价的;
  • 3.格式化输入输出函数:
scanf(x,)fscanf(stdin,x,)是等价的;
printf(x,)fprintf(stdout,x,)是等价的;

13、getchar失效问题

getchar失效问题,有两种解决办法:

1.在调用单字符输入函数getchar或者scanf("%c "…)之前,执行fflush函数清理一下输入缓冲区;

2.使用scanf("\n%c"…)代替getchar函数,可以很好地解决单字符输入失效的问题。

14、清空缓冲区fflush()函数

Ⅰ、fflush()函数
此函数包含在stdio.h头文件中,用来强制将缓冲区中的内容写入文件。

1.函数原型:

int fflush(FILE *stream) ;

2.函数功能:

清除一个流,即清除文件缓冲区.

3.适用场合:

一、ff(stdin)与fflush(stdout)的区别

ff(stdin)刷新标准输入缓冲区,把输入缓冲区里的东西丢弃

fflush(stdout)刷新标准输出缓冲区,把输出缓冲区里的东西打印到标准输出设备上。

二、scanf()函数接收输入数据时,结束一个数据的输入的情况

scanf()函数接收输入数据时,遇以下情况结束一个数据的输入:(不是结束该scanf函数, scanf函数仅在每一个数据域均有数据,并按回车后结束)。

① 遇空格、“回车”、“跳格”键。
② 遇宽度结束。
③ 遇非法输入。

遇到上面的情况,键盘缓冲区就可能有残余信息问题。

scanf()函数应该只是扫描stdin流,这个残存信息是在stdin中,要解决这个问题就要在scanf()函数之后加个fflush(stdin)。

三、文件与缓存

写文件的时候 不会马上进行物理磁盘的文件读写,而是先写入缓存,当缓存中内容达到一定程度后再写,例如:

FILE *fp=fopen("小柯南.txt","w");
fprintf(fp,"xiaokenan");
fflush(fp);
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值