C语言中文件操作

126 阅读8分钟

1 C语言中文件操作大概分几步

  • 使用fopen打开文件,选择打开模式

  • 使用文件相关api对文件进行读、写操作

  • 使用完成后释放文件指针关闭文件

2 文件打开方式

文件打开方式我们分为文本文件和二进制文件的打开方式,

文本文件打开方式有以下几种:

  • r:打开一个已经存在的文本文件,只能从文本文件中读取数据。如果指定文件不存在,程序就会出错。

  • w:打开一个文件文件,只能将数据写入文件。如果已经存在该文件名的文件,文件被重写:如果不存在,则以该文件名建立新的文件。

  • a:以附加方式打开文件,将数据写入文件的尾部。如果文件不存在,创建新的文件用于写入。

  • r+:打开一个已经存在的文本文件,可以从中读取数据,也可以写入数据。

  • w+:打开一个已经存在的文本文件,可以读取数据,也可以写入数据,若文件不存在,则自动建立一个新文件,接收写入的数据;若文件存在,则删去旧文件,建立一个同名新文件,接收写入的数据。 

  • a+:打开一个已经存在的文本文件,可以读取数据,也可以从当前文件的尾部追加写入数据。当文件不存在时,创建新的文件用于文件尾写入。

二进制文件打开方式

  • rb:打开一个已经存在的二进制文件,只能从二进制文件中读取数据。如果指定文件不存在,程序就会出错。 

  • wb:打开一个二制制文件,只能将数据写入文件。如果已经存在该文件名的文件,文件被重写;如果不存在,则以该文件名建立新的文件。

  • ab:打开一个已经存在的二进制文件,只能从当前文件的尾部追加写入数据。如果文件不存在,创建新的文件用于写入。

  • rb+:打开一个已经存在的二进制文件,可以从中读取数据,也可以写入数据。

  • wb+:打开一个已经存在的二进制文件,可以读取数据,也可以写入数据,若文件不存在,则自动建立一个新文件,接收写入的数据;若文件存在,则删去旧文件,建立个同名新文件,接收写入的数据。

  • ab+:打开一个已经存在的文本文件,可以读取数据,也可以从当前文件的尾部追加写入数据。当文件不存在时,创建新的文件用于文件尾写入。

其中,

r(read)表示读

w(write)表示写

a(append)表示添加

b(binary)表示二进制文件

3 文件读写

3.1  字符读写方式

这里准备了一个test.txt的文本文件,内容截图如下

3.1.1 读文件

首先创建一个fileName的文件指针,while循环中使用feof()对文件读取末尾进行判断,如果未到文件末尾则使用putchar()将字符一个个显示在屏幕上,最后使用fclose()关闭文件,释放资源。

        char *fileName = "E:\\test.txt";
	FILE *fp=fopen(fileName,"a+");
	if (fp == NULL) {
		printf("文件打开失败\n");
		exit(0);

	}
	else {
		printf("文件打开成功\n");
	}
	
	
	//读文件
	while (!feof(fp))
	{
		char ch=fgetc(fp);
		putchar(ch);
	}
        fclose(fileName);

运行截图如下:

3.1.2 写文件

下面代码是将字符串info写入到文件,while循环中通过指针逐个取字符,最后将info写到文件中。

        char *info = "hello world";
	fputc('\n', fp);
	while (*info !='\0')
	{
		fputc(*info,fp);

		info++;
	}

运行结果截图:

3.2 按照字符串方式读写

上面按字符方式读取,如果内容是英文的,那么读取是没问题的,但如果内容是中文的,那么读取就是乱码的(有兴趣的可以自己试下,将test.txt的文件内容换成中文进行读取,或者将info换成中文写入),所以我们需要以字符串方式来读取。

字符串方式的读写比单个字符读取效率更高。

我们使用字符串方式读写来实现一个文件的复制,用到的函数有fgets(),fputs()。

	FILE *origin, *dest;

	char *originName = "E:\\test.txt";
	char *destName = "E:\\test2.txt";
	//源文件
	origin = fopen(originName, "r");
	if (origin == NULL) {
		printf("文件不存在");
		exit(0);
	}

	//目标文件
	dest = fopen(destName, "w+");
	if (dest==NULL)
	{
		printf("打开文件失败");
		exit(0);
	}


	//开始复制文件内容
	char buf[1024];
	char *content= fgets(buf, sizeof(buf), origin);
	while (fgets(buf, sizeof(buf), origin) !=NULL)
	{
		fputs(buf,dest);

	}
        
        //关闭文件
	fclose(origin);
	fclose(dest);

运行结果如图:

3.3 二进制文件读写

读写二进制如果使用字符货字符串方式读取,肯定是不行的,这种方式肯定会出现乱码的情况,这时候我们就应该使用二进制的方式读写。

这里我们使用一张图片作为案例,将图片a.png复制一份儿,重新命名为b.png

    FILE *a_file, *b_file;
    char buffer[1024];
    size_t bytes_read;

    // 打开a.png文件
    a_file = fopen("E\\a.png", "rb");
    if (a_file == NULL) {
        printf("无法打开a.png文件!\n");
        return 1;
    }

    // 创建b.png文件
    b_file = fopen("E:\\b.png", "wb");
    if (b_file == NULL) {
        printf("无法创建b.png文件!\n");
        return 1;
    }

    // 从a.png读取数据并写入b.png
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), a_file)) > 0) {
        fwrite(buffer, 1, bytes_read, b_file);
    }

    // 关闭文件
    fclose(a_file);
    fclose(b_file);
yu

运行结果:

4 常见的文件操作函数说明

4.1 fopen()

函数原型:FILE *fopen(const char *filename, const char *mode)

函数说明:打开文件并返回文件指针,文件指针用于后续的文件读写操作。

参数说明:

  • filename:要打开的文件名。
  • mode:打开文件的模式,包括读、写、追加等模式。

返回值:文件指针,如果文件打开失败,则返回NULL。

4.2 fclose()

函数原型:int fclose(FILE *stream)

函数说明:关闭文件,释放文件指针。

参数说明:stream为要关闭的文件指针。

返回值:成功返回0,失败返回EOF。

4.3 fgets()

函数原型:char *fgets(char *str, int n, FILE *stream)

函数说明:从文件中读取一行数据,返回一个字符串。

参数说明:

  • str:读取的数据存放的缓冲区。
  • n:读取的最大字符数。
  • stream:要读取数据的文件指针。

返回值:成功返回读取的字符串,失败返回NULL。

4.4 fputc()

函数原型:int fputc(int c, FILE *stream)

函数说明:向文件中写入一个字符。

参数说明:

  • c:要写入的字符。
  • stream:要写入数据的文件指针。

返回值:成功返回写入的字符,失败返回EOF。

4.5 fputs()

函数原型:int fputs(const char *str, FILE *stream)

函数说明:向文件中写入一个字符串。

参数说明:

  • str:要写入的字符串。
  • stream:要写入数据的文件指针。

返回值:成功返回非负数,失败返回EOF。

4.6 fread()

函数原型:size_t fread(void *ptr, size_t size, size_t count, FILE *stream)

函数说明:从文件中读取数据到缓冲区中。

参数说明:

  • ptr:存放读取数据的缓冲区。
  • size:每个数据项的字节数。
  • count:要读取的数据项数。
  • stream:要读取数据的文件指针。

返回值:成功返回读取的数据项数,失败返回0。

4.7 fwrite()

函数原型:size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream)

函数说明:将缓冲区的数据写入文件中。

参数说明:

  • ptr:要写入文件的数据。
  • size:每个数据项的字节数。
  • count:要写入的数据项数。
  • stream:要写入数据的文件指针。

返回值:成功返回写入的数据项数,失败返回0。

4.8  fseek()

函数原型:int fseek(FILE *stream, long offset, int whence)

函数说明:设置文件指针的位置。

参数说明:

  • stream:要设置位置的文件指针。
  • offset:相对于whence的偏移量。
  • whence:设置偏移量的基准位置,包括文件开头、文件末尾等。

返回值:成功返回0,失败返回非0值。

4.9 ftell()

函数原型:long ftell(FILE *stream)

函数说明:获取文件指针的当前位置。

参数说明:stream为要获取位置的文件指针。

返回值:返回文件指针的当前位置。

4.10 rewind()

函数原型:void rewind(FILE *stream)

函数说明:将文件指针回到文件开头。

参数说明:stream为要回到开头的文件指针。

4.11 remove()

函数原型:int remove(const char *filename)

函数说明:删除文件。

参数说明:filename为要删除的文件名。

返回值:成功返回0,失败返回非0值。

4.12 rename()

函数原型:int rename(const char *oldname, const char *newname)

函数说明:重命名文件。

参数说明:

  • oldname:要重命名的文件名。

  • newname:新的文件名。

返回值:成功返回0,失败返回非0值。

4.13 feof()

函数原型:int feof(FILE *stream)

函数说明:判断文件是否已经结束。

参数说明:stream为要判断的文件指针。

返回值:如果文件已经结束,返回非0值,否则返回0。

4.14 perror()

函数原型:void perror(const char *s)

函数说明:输出文件操作错误信息。

参数说明:s为要输出的错误信息前缀。

返回值:无。

5 总结

后续使用过程中,碰到了再继续完善