一.文件指针

1.概述

(1)介绍

**介绍:**在C语言中,文件指针(FILE)是一种特殊的指针,用于指向文件。通过文件指针,我们可以对文件进行各种操作,如读取、写入、定位等

(2)底层

实际使用库函数,不用关心这个,只需要把这个传给库函数,库函数自然会通过FILE结构体里的信息对文件进行操作

底层: FILE其实是系统用typedef取了别名的一个包含文件名、文件当前位置等信息的结构体类型

//FILE在stdio.h文件中的文件类型声明
typedef  struct 
{  short level;   	    	   //缓冲区“满”或“空”的程度
    unsigned flags; 	   	   //文件状态标志
    char fd; 			      //文件描述符
    unsigned charhold; 	   //如无缓冲区不读取字符
    short bsize;       	   //缓冲区的大小
    unsigned char *buffer;     //数据缓冲区的位置 
    unsigned ar*curp;	   	   //指针,当前的指向 
    unsigned istemp;	   	   //临时文件,指示器 
    shorttoken;		   //用于有效性检查 
}FILE

(3)文件读取顺序

  • 先在内存中开辟一块空间,创建FILE结构体类型并存储文件相关信息
  • 将FILE结构体的地址交给指针
  • 实际由库函数通过指针操作文件
image-20240213161728891

(4)操作步骤

1、 对文件进行读写等操作之前要打开文件得到文件指针

  • 打开文件底层创建FILE结构体,并将地址交给指针

2、可以通过文件指针对文件进行读写等操作

  • 通过将指针传给操作函数,由操作函数通过指针找到FILE进行相关操作

3、读写等操作完毕后,要关闭文件,关闭文件后,就不能再通过此文件指针操作文件了

  • 读写完毕,传给结束函数,其通过指针找到FILE结构体并将其释放

2.定义

(1)格式

注意:FILE为大写,需要包含

格式:FILE *文件指针名;

二.补充知识

1.C语言缓冲区

缓冲区满自动刷新到内存、手动刷新到内存,这些和Java缓冲流没释放时机制一样,不过需要注意的是,它在程序结束时会自动刷新数据到磁盘,而Java不会

(1)刷新时机

1.缓冲区满了,刷新缓冲区

2.调用函数刷新缓冲区 fflush(文件指针)

3.程序结束 会刷新缓冲区

2.feof-检测是否读完

格式:feof(文件指针)

**功能:**检测流上的文件结束符

返回值:

  • 结束:非0
  • 未结束:0

3.特殊的文件指针

无需定义,在程序中可以直接使用

**stdi:**标准输入,默认为当前终端(键盘)

例:我们使用的scanf、getchar函数默认从此终端获得数据

stdout:标准输出,默认为当前终端(屏幕)

例:我们使用的printf、puts函数默认输出信息到此终端

stderr:标准错误输出设备文件,默认为当前终端(屏幕)

例:当我们程序出错使用:perror函数时信息打印在此终端

三.Fopen-打开文件

1.概述

(1)功能

fopen函数的功能是打开一个已经存在的文件,并返回这个文件的文件指针或者创建一个文件,并打开此文件,然后返回文件的标识

(2)注意事项

  • 使用完文件后,一定要使用 fclose 函数关闭文件,以释放系统资源
  • 在多线程程序中,需要小心使用 fopen,因为文件操作可能不是线程安全的

2.定义

(1)函数原型

参数:

  • filename:要打开的文件的名称(包括路径)
  • mode:打开文件的模式

函数原型:

FILE *fopen(const char *filename, const char *mode);

(2)返回值

使用时其打开文件一定要对返回值进行判断,看看是否打开成功

  • 如果文件成功打开,返回一个指向该文件的 FILE 结构体指针
  • 如果打开文件失败,返回 NULL

(3)打开模式

可以加上 "b" 字符以二进制模式打开文件,如:rb

  • "r":以只读方式打开文件。文件必须存在
  • "w":以只写方式打开文件。如果文件存在,则清空该文件;如果文件不存在,则创建新文件(会清空文件)
  • "a":以追加方式打开文件。如果文件存在,写入的数据会被添加到文件末尾;如果文件不存在,则创建新文件(不会清空文件)
  • "r+":以读写方式打开文件。文件必须存在
  • "w+":以读写方式打开文件。如果文件存在,则清空该文件;如果文件不存在,则创建新文件
  • "a+":以追加和读取方式打开文件。如果文件存在,写入的数据会被添加到文件末尾;如果文件不存在,则创建新文件

四.Fclose-关闭文件

1.概述

(1)功能

fclose用于关闭传入FILE指针所代表的文件

(2)注意事项

  • 调用fclose关闭文件后,就不能对文件进行任何操作了
  • 调用fclose关闭文件的同时,会刷新文件的缓冲数据到磁盘中

2.定义

(1)函数原型

参数:

  • stream:一个指向 FILE 结构体的指针

函数原型:

int fclose(FILE *stream);

(2)返回值

会返回一个整形,用来表示关闭的结果

  • 如果文件成功关闭,fclose 函数返回零(0
  • 如果发生错误,fclose 函数返回 EOF(在 中定义,通常为一个负数)

3.示例代码

#include 
#pragma warning(disable:4996)
int main() {

	FILE* file;
	file = fopen(".\\test.txt", "r");
	if (file != NULL) {
		printf("文件打开成功\n");
	}else {
		printf("文件打开失败\n");
		return 0;
	}

	int result = fclose(file);
	if (result == 0) {
		printf("文件关闭成功\n");
	}else {
		printf("文件关闭失败\n");
		return 0;
	}
	return 0;
}

五.按字节读写

1.Fgetc-按字节读

(1)概述

① 介绍

fgetc从stream所标识的文件中读取一个字节,将字节值返回

② 注意事项
  • 要确保文件打开并处于正确的读取模式、
  • 读取完毕后,要记得释放文件

(2)定义

① 函数原型

参数:

  • stream:一个指向 FILE 结构体的指针,该结构体代表一个打开的文件流。

函数原型:

int fgetc(FILE *stream);
② 返回值
  • 以文本(t)读:读到文件结尾返回EOF
  • 以二进制(b)读:读到文件结尾,需要使用feof(文件指针)判断是否结尾

2.fputc-按字节写

(1)概述

① 介绍

fputc 是 C 语言标准库中的一个函数,用于将指定的字符写入到给定的文件流中。这个函数通常用于文件写入操作,将单个字符或字符串中的字符逐一写入到文件中

② 注意事项
  • 要确保文件打开并处于正确的读取模式、
  • 读取完毕后,要记得释放文件

(2)定义

① 函数原型

参数:

  • character:要写入文件的字符的 ASCII 值。
  • stream:一个指向 FILE 结构体的指针,该结构体代表一个打开的文件流。

函数原型:

int fputc(int character, FILE *stream);
② 返回值
  • 如果成功写入字符,fputc 返回写入的字符。
  • 如果发生写入错误,fputc 返回 EOF

3.读写示例

(1)概述

用a进行读写,会从末尾开始,每写一个向后移一个

打开文件时,默认的读写位置是文件的开始,然后不断向后读取,每读一个字节,读的位置就会往文件的末尾偏移多少个字节

(2)范例

代码: 这里是将结果写到屏幕上,也可以指定一个文件指针,让数据写到文件中

#include 
#pragma warning(disable:4996)
int main() {

	FILE* file;
	file = fopen(".\\FileTest\\test.txt", "r");
	if (file != NULL) {
		printf("文件打开成功\n");
	}
	else {
		printf("文件打开失败\n");
		return 0;
	}

	int d;
	while ((d = fgetc(file)) != EOF) {
		//stdout是标准输出,默认输出到屏幕。是一个无需定义的指针
		fputc(d, stdout);
	}
	printf("\n");
	int result = fclose(file);
	if (result == 0) {
		printf("文件关闭成功\n");
	}
	else {
		printf("文件关闭失败\n");
		return 0;
	}
	return 0;
}

返回值:

文件打开成功
helloWorld!
文件关闭成功

六.按行读写字符串

类似于Java中带缓冲的字符输入输出流的Read和

1.Fgets-按行读

(1)概述

① 介绍

fgets 是 C 语言中的一个标准库函数,用于从指定的文件流中读取一行数据,

② 注意事项
  • 实际读取的字符数会是"实际字符数-1",因为其为\0预留空间
  • 遇到换行符(\n)、文件结束符(EOF)或已达到指定的最大字符数(包括空字符 '\0'

(2)定义

① 函数原型

参数:

  • str:指向存储读取的字符串数组的指针
  • n:要读取的最大字符数(包括空字符 '\0'
    • 通常,这个值会是目标字符数组的大小
  • stream:指向 FILE 对象的指针,该对象表示一个输入流

函数原型:

char *fgets(char *str, int n, FILE *stream);
② 返回值
  • 如果成功读取一行数据,fgets 会返回 str 的指针。
  • 如果到达文件末尾或发生读取错误,fgets 会返回 NULL

2.Fputs-按行写

(1)概述

fputs 是 C 语言标准库中的一个函数,用于将字符串写入到指定的文件流中。

(2)定义

① 函数原型

参数:

  • str:指向要写入文件的字符串的指针。
  • stream:指向 FILE 对象的指针,该对象表示一个输出流。

函数原型:

int fputs(const char *str, FILE *stream);
② 返回值
  • 如果成功写入字符串,fputs 返回非负值
  • 如果发生写入错误,fputs 返回 EOF

3.示例代码

perror:打印错误信息,除自定义信息外还显示日志

用于拷贝test.txt文件到back.txt文件

#include 
#pragma warning(disable:4996)

int main() {
	FILE* fileInp;
	fileInp = fopen(".\\FileTest\\test.txt", "r");
	if (fileInp != NULL) {
		printf("文件打开成功\n");
	}
	else {
		perror("文件打开失败\n");
		return 0;
	}
	FILE* fileOut;
	fileOut = fopen(".\\FileTest\\back.txt", "w");
	if (fileOut != NULL) {
		printf("文件打开成功\n");
	}
	else {
		perror("文件打开失败\n");
		return 0;
	}

	char str[50];
	while ((fgets(str, 50, fileInp)) != NULL) {
		fputs(str, fileOut);
	}
	int result = fclose(fileOut);
	if (result == 0) {
		printf("文件关闭成功\n");
	}
	else {
		perror("文件关闭失败\n");
		return 0;
	}
	int result1 = fclose(fileInp);
	if (result1 == 0) {
		printf("文件关闭成功\n");
	}
	else {
		perror("文件关闭失败\n");
		return 0;
	}
	return 0;
}

七.按块读

1.fread-读文件

(1)概述

① 介绍

C 语言中的一个函数,用于从文件流中读取数据块。它是定义在 头文件中的

② 注意事项
  • 调用 fread 前需要确保文件已经打开,且没有到达文件末尾(EOF)。
  • 读取的数据会按照 size 指定的字节长度连续存储在 ptr 指向的内存区域中。
  • 如果 fread 的调用导致读取的数据超出文件末尾,返回值将小于 count
  • 在多线程环境中使用 fread 时,需要确保对同一个 FILE *stream 的操作是互斥的,因为标准的 FILE 缓冲区不是线程安全的。

(2)定义

① 函数原型

参数:

  • ptr: 指向用于存储读取的数据的缓冲区的指针
    • 一般就是一个数组
  • size: 每个读取的数据块的大小,以字节为单位
  • count: 要读取的数据块个数
  • stream: 指向 FILE 对象的指针,该对象标识了要从中读取数据的文件流

函数原型:

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

示例:

从fp所代表的文件中读取内容存放到str指向的内存中,读取的字节数为 ,每块100个字节,3块

fread(str,100,3,fp);
② 返回值
  • 如果读取成功,返回实际读取的数据块的个数
    • 如果获取的数据量大于一个数据块小于第二个数据块,会返回1
  • 如果到达文件末尾,或者发生错误,返回0

2.fwrite-写文件

(1)概述

① 介绍

fwrite 是 C 语言中用于向文件流写入数据的函数。它是定义在 头文件中的

② 注意事项
  • 在调用 fwrite 之前,必须先打开文件,并指定合适的打开模式,如 wb(二进制写入)、w(文本写入)等。
  • 写入的数据不会自动终止于空字符,这意味着如果要写入字符串,必须显式包含终止的空字符,或者使用 fputc 单独写入空字符。
  • 对于二进制文件,fwrite 是格式化的,意味着它会原封不动地写入数据,而不会进行任何转换。

(2)定义

① 函数原型

参数:

  • const void *ptr: 指向要写入文件的数据的指针
  • size: 每个数据块的大小,单位是字节
  • count: 要写入的数据块的数量
  • FILE *stream: 指向 FILE 对象的指针,该对象标识了要向其写入数据的文件流

函数原型:

size_t fwrite(const void *ptr, size_t size, size_t count, FILE *stream);
② 返回值
  • 返回实际写入的数据块数量。

3.示例代码

类似于Java 中字符流的 read 方法使用数组读取数据

这个示例假设你已经有一个名为source.txt的源文件。它将打开source.txt文件,读取其内容,并将内容写入一个名为destination.txt的目标文件中。

#include 
#include 

int main() {
    FILE *source_file, *destination_file;
    char buffer[1024];
    size_t bytes_read;

    // 打开源文件
    source_file = fopen("source.txt", "rb");
    if (source_file == NULL) {
        perror("Error opening source file");
        return EXIT_FAILURE;
    }

    // 创建目标文件
    destination_file = fopen("destination.txt", "wb");
    if (destination_file == NULL) {
        perror("Error creating destination file");
        fclose(source_file);
        return EXIT_FAILURE;
    }

    // 从源文件读取内容并写入目标文件
    while ((bytes_read = fread(buffer, 1, sizeof(buffer), source_file)) > 0) {
        fwrite(buffer, 1, bytes_read, destination_file);
    }

    // 关闭文件
    fclose(source_file);
    fclose(destination_file);

    printf("File copied successfully.\n");

    return EXIT_SUCCESS;
}

八.控制读写位置

1.Rewind函数

(1)概述

① 介绍

rewind() 是C 语言标准库 中的一个函数,用于将文件指针(file pointer)重新定位到文件的开始位置

② 应用
  • rewind() 函数将文件指针移动到文件的开始位置,即使之前已经读取或写入了文件的内容,也会将指针重新设置到开头
  • 这个函数通常用于需要重新读取文件内容的情况,或者对文件进行后续操作之前需要确保指针位置的情况
③ 注意事项
  • 在调用 rewind() 函数之前,应确保已经成功打开了文件,并且文件指针有效。
  • 使用 rewind() 函数可能会导致之前的读取或写入操作失效,因为它将文件指针重新设置到开始位置,因此请小心使用

(2)函数原型

  • stream 是指向 FILE 物件的指针,它代表了要复位的文件
void rewind(FILE *stream);

(3)示例

第一次读取完文件后,对齐复位后再进行读取,两次读取的内容是一样的

#include 
   
int main() {
    FILE *fp;
    char ch;
   
    // 开启文件以供读取
    fp = fopen("example.txt", "r");
    if (fp == NULL) {
        printf("无法打开文件。\n");
        return -1;
    }
   
    // 读取并输出文件的内容
    while ((ch = fgetc(fp)) != EOF) {
        printf("%c", ch);
    }
   
    // 将文件指针复位到开始位置
    rewind(fp);
   
    // 再次读取并输出文件的内容
    printf("\n\n复位后再次读取文件的内容:\n");
    while ((ch = fgetc(fp)) != EOF) {
        printf("%c", ch);
    }
   
    // 关闭文件
    fclose(fp);
    return 0;
}

2.Ftell函数

(1)概述

① 介绍
  • ftell 是C语言标准库 中的一个函数,用于获取文件位置指针当前位置相对于文件开头的偏移量
② 注意事项
  • ftell 返回的位置是以字节为单位的,所以在二进制模式下使用时要特别注意
  • 返回值的类型是 long int,因此对于非常大的文件可能会有限制

(2)定义

① 函数原型
  • stream:指向 FILE 结构的指针,代表已经打开的文件
long int ftell(FILE *stream);
② 返回值
  • 获取位置成功,就会返回 long int 类型的值,表示当前位置相对于文件开头的字节偏移量
  • 获取位置失败,就会返回-1

(3)代码

通过 ftell 函数来获取文件位置指针的当前位置相对于文件开头的偏移量,如果返回-1,就直接保持退出,否则就正常写出偏移量

   #include 

   int main() {
       FILE *file;
       long int position;

       file = fopen("example.txt", "r");
       if (file == NULL) {
           perror("Error opening file");
           return -1;
       }

       // 获取当前位置
       position = ftell(file);
       if (position == -1) {
           perror("Error getting file position");
           fclose(file);
           return -1;
       }

       printf("Current position: %ld\n", position);

       fclose(file);
       return 0;
   }

3.fseek函数

(1)概述

① 介绍
  • fseek 是C语言标准库 中的一个函数,用于在文件中设置文件位置指针的位置
  • 可以用于定位文件中的特定位置,以便进行读取或写入操作
② 注意事项
  • fseek 可以用于定位到文件的任意位置,但在使用时要小心,特别是在二进制文件中
  • 在使用 fseek 之前,文件必须以适当的模式打开

(2)定义

① 函数原型
int fseek(FILE *stream, long int offset, int whence);
② 参数说明
  • stream:指向 FILE 结构的指针,代表已经打开的文件。
  • offset:偏移量,表示从 whence 指示的位置开始的偏移量,单位为字节。
  • whence:指示偏移量相对于何处的参数,可选值为 SEEK_SETSEEK_CURSEEK_END,分别表示从文件开头、当前位置或文件末尾开始计算偏移量。
③ 返回值
  • 返回 int 类型的值,表示函数执行的状态。
  • 如果执行成功,返回 0;如果发生错误,返回非零值,并设置 errno
④ 示例

这段程式码使用了 fseek() 将档案指标移动到档案的结尾,然后使用 ftell() 来获取从文件开头到结尾位置的偏移值,这个值可以当作文件的大小。

   #include 

   int main() {
       FILE *file;

       file = fopen("example.txt", "r");
       if (file == NULL) {
           perror("Error opening file");
           return -1;
       }

       // 将文件位置指针移动到文件末尾
       if (fseek(file, 0, SEEK_END) != 0) {
           perror("Error seeking to end of file");
           fclose(file);
           return -1;
       }

       // 获取文件末尾的位置
       long int end_position = ftell(file);
       if (end_position == -1) {
           perror("Error getting file position");
           fclose(file);
           return -1;
       }

       printf("End of file position: %ld\n", end_position);

       fclose(file);
       return 0;
   }
最后修改:2024 年 03 月 11 日
如果觉得我的文章对你有用,请随意赞赏