C语言 文件操作相关函数

Posted 流楚丶格念

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C语言 文件操作相关函数相关的知识,希望对你有一定的参考价值。

头文件:stdio.h

#include <stdio.h> 

文件打开关闭函数

文件打开(fopen)

文件的打开操作表示将给用户指定的文件在内存分配一个FILE结构区,并将该结构的指针返回给用户程序,以后用户程序就可用此FILE指针来实现对指定文件的存取操作了。当使用打开函数时,必须给出文件名、文件操作方式(读、写或读写)。

FILE * fopen(const char * filename, const char * mode);
  • 功能:打开文件
  • 参数:
    filename:需要打开的文件名,根据需要加上路径
    mode:打开文件的权限设置
  • 返回值:
    成功:文件指针
    失败:NULL

参数mode可选值

方式含义
“r”打开,只读,文件必须已经存在。
“w”只写,如果文件不存在则创建,如果文件已存在则把文件长度截断(Truncate)为0字节。再重新写,也就是替换掉原来的文件内容文件指针指到头。
“a”只能在文件末尾追加数据,如果文件不存在则创建
“rb”打开一个二进制文件,只读
“wb”打开一个二进制文件,只写
“ab"打开一个二进制文件,追加
“r+”允许读和写,文件必须已存在
“w+”允许读和写,如果文件不存在则创建,如果文件已存在则把文件长度截断为0字节再重新写 。
“a+”允许读和追加数据,如果文件不存在则创建
“rb+”以读/写方式打开一个二进制文件
“wb+”以读/写方式建立一个新的二进制文件
“ab+”以读/写方式打开一个二进制文件进行追加

案例

检查fopen的返回值:
如何函数失败,它会返回一个NULL值。如果程序不检查错误,这个NULL指针就会传给后续的I/O函数。它们将对这个指针执行间接访问,并将失败

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void test() {

	FILE *fp = NULL;

	// "\\\\"这样的路径形式,只能在windows使用
	// "/"这样的路径形式,windows和linux平台下都可用,建议使用这种
	// 路径可以是相对路径,也可是绝对路径
	fp = fopen("../test", "w");
	//fp = fopen("..\\\\test", "w");

	if (fp == NULL) //返回空,说明打开失败
	{
		//perror()是标准出错打印函数,能打印调用库函数出错原因
		perror("open");
		return;
	}
}

int main()
{
	test();
	return 0;
}

文件关闭(fclose)

文件操作完成后,如果程序没有结束,必须要用fclose()函数进行关闭,这是因为对打开的文件进行写入时,若文件缓冲区的空间未被写入的内容填满,这些内容不会写到打开的文件中。只有对打开的文件进行关闭操作时,停留在文件缓冲区的内容才能写到该文件中去,从而使文件完整。再者一旦关闭了文件,该文件对应的FILE结构将被释放,从而使关闭的文件得到保护,因为这时对该文件的存取操作将不会进行。文件的关闭也意味着释放了该文件的缓冲区。

int fclose(FILE * stream);
  • 功能:关闭先前fopen()打开的文件。此动作让缓冲区的数据写入文件中,并释放系统所提供的文件资源。
  • 参数:
    stream:文件指针
  • 返回值:
    成功:0
    失败:-1

它表示该函数将关闭FILE指针对应的文件,并返回一个整数值。若成功地关闭了文件,则返回一个0值,否则返回一个非0值.

文件读写相关函数

总览

文件读写相关基本函数包括以下几个方面:

  • 按照字符读写文件:fgetc(), fputc()
  • 按照行读写文件:fputs(), fgets()
  • 按照块读写文件:fread(), fwirte()
  • 按照格式化读写文件:fprintf(), fscanf()
  • 按照随机位置读写文件:fseek(), ftell(), rewind()

字符读写函数

int fputc(int ch, FILE * stream);
  • 功能:将ch转换为unsigned char后写入stream指定的文件中
  • 参数:
    ch:需要写入文件的字符
    stream:文件指针
  • 返回值:
    成功:成功写入文件的字符
    失败:返回-1
int fgetc(FILE * stream);
  • 功能:从stream指定的文件中读取一个字符
  • 参数:
    stream:文件指针
  • 返回值:
    成功:返回读取到的字符
    失败:-1
int feof(FILE * stream);
  • 功能:检测是否读取到了文件结尾
  • 参数:
    stream:文件指针
  • 返回值:
    非0值:已经到文件结尾
    0:没有到文件结尾

字符读写案例

将把流指针fp指向的文件中的一个字符读出,并赋给ch,当执行fgetc()函数时,若当时文件指针指到文件尾,即遇到文件结束标志EOF(其对应值为-1),该函数返回一个 -1 给ch,在程序中常用检查该函数返回值是否为 -1 来判断是否已读到文件尾,从而决定是否继续。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void test() {

	//写文件
	FILE* fp_write = NULL;
	//写方式打开文件
	fp_write = fopen("./mydata.txt", "w+");
	if (fp_write == NULL) {
		return;
	}

	char buf[] = "this is a test for pfutc!";
	for (int i = 0; i < strlen(buf); i++) {
		fputc(buf[i], fp_write);
	}

	fclose(fp_write);

	//读文件
	FILE* fp_read = NULL;
	fp_read = fopen("./mydata.txt", "r");
	if (fp_read == NULL) {
		return;
	}

#if 1
	//判断文件结尾 注意:多输出一个空格
	while (!feof(fp_read)) {
		printf("%c", fgetc(fp_read));
	}
#else
	char ch;
	while ((ch = fgetc(fp_read)) != EOF) {
		printf("%c", ch);
	}
#endif
}

int main()
{
	test();
	return 0;
}

输出结果为:

行读写函数

int fputs(const char * str, FILE * stream);
  • 功能:将str所指定的字符串写入到stream指定的文件中, 字符串结束符 ‘\\0’ 不写入文件。
  • 参数:
    str:字符串
    stream:文件指针
  • 返回值:
    成功:0
    失败:-1
char * fgets(char * str, int size, FILE * stream);
  • 功能:从stream指定的文件内读入字符,保存到str所指定的内存空间,直到出现换行字符、读到文件结尾或是已读了size - 1个字符为止,最后会自动加上字符 ‘\\0’ 作为字符串结束。
  • 参数:
    str:字符串
    size:指定最大读取字符串的长度(size - 1)
    stream:文件指针
  • 返回值:
    成功:成功读取的字符串
    读到文件尾或出错: NULL

行读写案例

往文件中写入四行,并读出输出。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void test() {

	//写文件
	FILE* fp_write = NULL;
	//写方式打开文件
	fp_write = fopen("./mydata.txt", "w+");
	if (fp_write == NULL) {
		perror("fopen:");
		return;
	}

	char* buf[] = {
		"01 倩 this is a test for pfutc!\\n",
		"02 倩 this is a test for pfutc!\\n",
		"03 倩 this is a test for pfutc!\\n",
		"04 倩 this is a test for pfutc!\\n",
	};
	for (int i = 0; i < 4; i++) {
		fputs(buf[i], fp_write);
	}

	fclose(fp_write);

	//读文件
	FILE* fp_read = NULL;
	fp_read = fopen("./mydata.txt", "r");
	if (fp_read == NULL) {
		perror("fopen:");
		return;
	}

	//判断文件结尾
	while (!feof(fp_read)) {
		char temp[1024] = { 0 };
		fgets(temp, 1024, fp_read);
		printf("%s", temp);
	}

	fclose(fp_read);
}


int main()
{
	test();
	return 0;
}

运行结果为:

块读写函数

size_t fwrite(
	const void *ptr, 
	size_t size, 
	size_t nmemb, 
	FILE *stream
);
  • 功能:以数据块的方式给文件写入内容
  • 参数:
    ptr:准备写入文件数据的地址
    sizesize_tunsigned int类型,此参数指定写入文件内容的块数据大小
    nmemb:写入文件的块数,写入文件数据总大小为:size * nmemb
    stream:已经打开的文件指针
  • 返回值:
    成功:实际成功写入文件数据的块数,此值和nmemb相等
    失败:0
size_t fread(
	void *ptr, 
	size_t size, 
	size_t nmemb, 
	FILE *stream
);
  • 功能:以数据块的方式从文件中读取内容
  • 参数:
    ptr:存放读取出来数据的内存空间
    sizesize_tunsigned int类型,此参数指定读取文件内容的块数据大小
    nmemb:读取文件的块数,读取文件数据总大小为:size * nmemb
    stream:已经打开的文件指针
  • 返回值:
    成功:实际成功读取到内容的块数,如果此值比nmemb小,但大于0,说明读到文件的结尾。
    失败:0

块读写案例

建立教师结构体,写入老师信息,并从文件中读取信息输出:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

// 老师结构体
typedef struct _TEACHER {
	char name[64];
	int age;
}Teacher;

void test() {
	//写文件
	FILE* fp_write = NULL;
	//写方式打开文件
	fp_write = fopen("./mydata.txt", "wb");
	if (fp_write == NULL) {
		perror("fopen:");
		return;
	}

	Teacher teachers[4] = {
		{ "倩", 33 },
		{ "利", 28 },
		{ "Jos", 45},
		{ "咪咪", 35}
	};

	for (int i = 0; i < 4; i++) {
		fwrite(&teachers[i], sizeof(Teacher), 1, fp_write);
	}
	//关闭文件
	fclose(fp_write);

	//读文件
	FILE* fp_read = NULL;
	fp_read = fopen("./mydata.txt", "rb");
	if (fp_read == NULL) {
		perror("fopen:");
		return;
	}

	Teacher temps[4];
	fread(&temps, sizeof(Teacher), 4, fp_read);
	printf("输出老师们的信息:\\n");
	for (int i = 0; i < 4; i++) {
		printf("姓名:%s  年龄:%d\\n", temps[i].name, temps[i].age);
	}

	fclose(fp_read);
}


int main()
{
	test();
	return 0;
}

运行结果为:

格式化读写函数

int fprintf(FILE * stream, const char * format, ...);
  • 功能:根据参数format字符串来转换并格式化数据,然后将结果输出到stream指定的文件中,指定出现字符串结束符'\\0'为止。
  • 参数:
    stream:已经打开的文件
    format:字符串格式,用法和printf()一样
  • 返回值:
    成功:实际写入文件的字符个数
    失败:-1
int fscanf(FILE * stream, const char * format, ...);
  • 功能:从stream指定的文件读取字符串,并根据参数format字符串来转换并格式化数据。
  • 参数:
    stream:已经打开的文件
    format:字符串格式,用法和scanf()一样
  • 返回值:
    成功:实际从文件中读取的字符个数
    失败: - 1

注意:fscanf遇到空格和换行时结束。

格式化读写案例

写入一行带空格的字符串,读取输出:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

void test() {

	//写文件
	FILE* fp_write = NULL;
	//写方式打开文件
	fp_write = fopen("./mydata.txt", "w");
	if (fp_write == NULL) {
		perror("fopen:");
		return;
	}

	fprintf(fp_write, "he llo wor ld :%d!", 99999);

	//关闭文件
	fclose(fp_write);

	//读文件
	FILE* fp_read = NULL;
	fp_read = fopen("./mydata.txt", "rb");
	if (fp_read == NULL) {
		perror("fopen:");
		return;
	}

	char temps[1024] = { 0 };
	while (!feof(fp_read)) {
		fscanf(fp_read, "%s", temps);
		printf("%s", temps);
	}

	fclose(fp_read);
}

int main()
{
	test();
	return 0;
}

随机读写函数

注意:这里的随机读写,不是系统随机位置就真随意读写了,是你要指定的随意位置进行读写

int fseek(FILE *stream, long offset, int whence);
  • 功能:移动文件流(文件光标)的读写位置。
  • 参数:
    stream:已经打开的文件指针
    offset:根据whence来移动的位移数(偏移量),可以是正数,也可以负数,如果正数,则相对于whence往右移动,如果是负数,则相对于whence往左移动。如果向前移动的字节数超过了文件开头则出错返回,如果向后移动的字节数超过了 文件末尾,再次写入时将增大文件尺寸。
    whence:其取值如下:
    • SEEK_SET:从文件开头移动offset个字节
    • SEEK_CUR:从当前位置移动offset个字节
    • SEEK_END:从文件末尾移动offset个字节
  • 返回值:
    成功:0
    失败:-1
long ftell(FILE *stream);
  • 功能:获取文件流(文件光标)的读写位置。
  • 参数:
    stream:已经打开的文件指针
  • 返回值:
    成功:当前文件流(文件光标)的读写位置
    失败:-1
void rewind(FILE *stream);
  • 功能:把文件流(文件光标)的读写位置移动到文件开头。
  • 参数:
    stream:已经打开的文件指针
  • 返回值:
    无返回值

随机读写案例

随机位置读取不同老师:

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

typedef struct _TEACHER {
	char name[64];
	int age;
}Teacher;

void test() {
	//写文件
	FILE* fp_write = NULL;
	//写方式打开文件
	fp_write = fopen("./mydata.txt", "wb");
	if (fp_write == NULL) {
		perror("fopen:");
		return;
	}

	Teacher teachers[4] = {
		{ "1倩", 33 },
		{ "2利", 28 },
		{ "3Jos", 45},
		{ "4咪咪", 35}
	};

	for (int i = 0; i < 4; i++) {
		fwrite(&teachers[i], sizeof(Teacher), 1, fp_write);
	}
	//关闭文件
	fclose(fp_write);

	//读文件
	FILE* fp_read = NULL;
	fp_read = fopen("./mydata.txt", "rb");
	if (fp_read == NULL) {
		perror("fopen:");
		return;
	}

	Teacher temp;
	// 从文件开头移动:读取第三个
	fseek(fp_read, sizeof(Teacher) * 2, SEEK_SET);
	fread(&temp, sizeof(Teacher), 1, fp_read);
	printf("Name:%s Age:%d\\n", temp.name, temp.age);

	memset(&temp, 0, sizeof(Teacher));

	// 从文件末尾移动:读取第四个
	fseek(fp_read, -(int)sizeof(Teacher), SEEK_END);
	fread(&temp, sizeof(Teacher), 1, fp_read);
	printf("Name:%s Age:%d\\n", temp.name, temp.age);

	// 重新从文件开头读取
	rewind(fp_read);
	fread(&temp, sizeof(Teacher), 1, fp_read);
	printf("Name:%s Age:%d\\n", temp.name, temp.age);

	fclose(fp_read);
}

int main()
{
	test();
	return 0;
}

运行结果为:

文件操作综合案例

内容较多,请移驾另一篇博客:https://yangyongli.blog.csdn.net/article/det

以上是关于C语言 文件操作相关函数的主要内容,如果未能解决你的问题,请参考以下文章

C语言文件的相关操作

C语言 文件操作相关概念

C语言 文件操作相关概念

C语言最文件操作函数(2)

c语言文件操作函数

C语言文件及其相关函数