目录
一、文件的打开和关闭
文件打开
fopen是 C 语言标准库中的一个非常重要的函数,用于打开文件。
//打开文件
FILE * fopen ( const char * filename, const char * mode );
//关闭文件
int fclose ( FILE * stream );
文件打开参数
filename
:
-
这是一个指向以空字符结尾的字符串的指针,该字符串指定了要打开的文件的名称。可以是相对路径或绝对路径。例如:
"example.txt"
表示当前目录下的example.txt
文件;"/home/user/documents/report.txt"
则是一个绝对路径。
mode
:
- 这也是一个指向以空字符结尾的字符串的指针,用于指定文件的打开模式。常见的打开模式如下:
"r"
:以只读模式打开文件。文件必须存在,否则打开失败。"w"
:以写入模式打开文件。如果文件不存在,则创建该文件;如果文件已存在,则清空文件内容。"a"
:以追加模式打开文件。如果文件不存在,则创建该文件;如果文件已存在,则在文件末尾追加数据。"r+"
:以读写模式打开文件。文件必须存在。"w+"
:以读写模式打开文件。如果文件不存在,则创建该文件;如果文件已存在,则清空文件内容。"a+"
:以读写模式打开文件。如果文件不存在,则创建该文件;如果文件已存在,则在文件末尾追加数返回值
返回值
- 如果文件成功打开,
fopen
函数返回一个指向FILE
类型对象的指针,该对象包含了文件的相关信息,后续可以使用这个指针进行文件的读写操作。 - 如果文件打开失败,
fopen
函数返回NULL
。可以通过检查返回值是否为NULL
来判断文件是否成功打开。
在 C 语言里,int fclose ( FILE * stream );
是一个标准库函数,其作用是关闭指定的文件流。
文件关闭
文件关闭参数
stream
:
- 这是一个指向
FILE
对象的指针,此对象代表着要关闭的文件流。FILE
对象是在使用fopen
函数打开文件时创建的。
返回值
- 若文件流成功关闭,函数会返回 0。
- 若在关闭过程中出现错误,函数将返回
EOF
(通常为 -1)。
注意事项
- 关闭文件流之后,就不能再使用该文件流指针进行读写操作,不然会产生未定义行为。
- 为了防止资源泄漏,在使用完文件流之后,一定要调用
fclose
函数将其关闭。 - 若在程序中打开了多个文件流,需要分别调用
fclose
函数将它们关闭。
二、文件和标准输入输出流操作
1.字符输入函数 fgetc
int fgetc(FILE *stream);
参数说明
stream
:这是一个指向FILE
类型对象的指针,代表着要进行读取操作的输入流。这个输入流既可以是通过fopen
函数打开的文件流,也可以是标准输入流stdin
(用于从键盘读取字符)。
返回值
- 成功读取:函数会返回读取到的字符,以
int
类型表示。虽然返回的是字符,但使用int
类型是为了能够表示文件结束符EOF
(通常定义为 -1)。 - 到达文件末尾:当读取到文件的末尾时,函数会返回
EOF
。 - 发生错误:如果在读取过程中发生错误,同样会返回
EOF
。可以通过调用ferror
函数来区分是到达文件末尾还是发生了错误。
功能说明
fgetc
函数的核心功能是从指定的输入流中读取一个字符,并将文件指针移动到下一个字符的位置。每调用一次 fgetc
函数,就会从输入流中读取一个字符,直到遇到文件结束符或者发生错误。
2.字符输出函数 fputc
int fputc(int character, FILE *stream);
参数说明
character
:这是要写入输出流的字符。尽管参数类型为int
,但实际上是把该int
类型值所对应的字符写入输出流。在传入时,可直接传入字符常量(如'A'
),也可以传入字符对应的 ASCII 码值。stream
:指向FILE
对象的指针,代表着要进行写入操作的输出流。该输出流可以是文件流(通过fopen
函数打开文件得到),也可以是标准输出流stdout
(即向屏幕输出字符)。
返回值
- 成功写入:函数返回写入的字符(以
int
类型表示)。 - 发生错误:若在写入过程中出现错误,函数返回
EOF
(通常为 -1)。
功能说明
fputc
函数的主要功能是把指定的字符写入到给定的输出流中,并且会将文件指针移动到下一个写入位置。每调用一次 fputc
函数,就会向输出流写入一个字符。
3.文本行输入函数 fgets
char *fgets(char *str, int num, FILE *stream);
参数说明
str
:这是一个char
类型的指针,指向用于存储读取到的字符串的字符数组。调用者需要确保该数组有足够的空间来存放读取的内容,包含字符串结束符'\0'
。num
:为int
类型的整数,它规定了最多读取的字符数量。fgets
函数最多会读取num - 1
个字符,然后在字符串末尾添加'\0'
以构成一个完整的字符串。这么做是为了避免缓冲区溢出,确保不会超出str
所指向数组的边界。stream
:是FILE
类型的指针,指向代表要读取数据的输入流的FILE
对象。该输入流可以是文件流(通过fopen
函数打开文件得到),也可以是标准输入流stdin
(即从键盘读取数据)。
返回值
- 功能:从指定的输入流
stream
中读取一行字符,最多读取num - 1
个字符,然后在字符串末尾添加'\0'
使其成为一个字符串。该流可以是文件流,也可以是标准输入流stdin
。 - 返回值:成功时返回指向
str
的指针,到达文件末尾或发生错误时返回NULL
。
功能说明
fgets
函数会从指定的输入流中读取字符,直到满足以下条件之一:
- 读取了
num - 1
个字符。 - 遇到换行符
'\n'
。此时,换行符也会被读取到字符串中。 - 遇到文件结束符(EOF)。
4.文本行输出函数 fputs
int fputs(const char *str, FILE *stream);
参数说明
str
:这是一个指向以'\0'
结尾的字符串的指针。该字符串就是要写入到输出流中的内容。stream
:指向FILE
类型对象的指针,代表要进行写入操作的输出流。它既可以是通过fopen
函数打开的文件流,也可以是标准输出流stdout
(用于向屏幕输出)。
返回值
- 成功写入:如果字符串成功写入到输出流,
fputs
函数返回一个非负整数。 - 发生错误:若在写入过程中出现错误,函数返回
EOF
(通常定义为 -1)。
功能说明
fputs
函数会将 str
所指向的字符串写入到指定的输出流中,但不会自动添加换行符。也就是说,它只会写入字符串本身,直到遇到字符串结束符 '\0'
为止。
5.格式化输入函数 fscanf
int fscanf(FILE *stream, const char *format, ...);
参数说明
stream
:这是一个指向FILE
类型对象的指针,代表要从中读取数据的输入流。输入流可以是文件流(通过fopen
函数打开文件得到),也可以是标准输入流stdin
(用于从键盘读取数据)。format
:是一个格式控制字符串,它规定了输入数据的格式。format
字符串中可以包含普通字符和格式说明符。普通字符必须与输入流中的字符严格匹配,而格式说明符用于指定读取的数据类型,常见的格式说明符有:%d
:读取十进制整数。%f
:读取浮点数。%s
:读取字符串(遇到空白字符停止)。%c
:读取单个字符。
...
:这是可变参数列表,用于接收从输入流中读取的数据。参数的数量和类型要与format
字符串中的格式说明符一一对应,并且每个参数都应该是一个变量的地址(即指针),这样fscanf
才能将读取的数据存储到这些变量中。- 成功匹配并赋值的输入项数量。
- 如果在读取过程中遇到文件结束符(EOF),则返回
EOF
。 - 如果发生读取错误,也会返回一个小于预期匹配项数量的值。
返回值
- 成功匹配并赋值的输入项数量:
fscanf
函数会返回成功匹配并赋值的输入项的数量。例如,如果format
字符串中有三个格式说明符,且都成功匹配并赋值给相应的变量,那么fscanf
会返回 3。 EOF
:如果在读取过程中遇到文件结束符(EOF),或者发生读取错误,fscanf
会返回EOF
(通常定义为 -1)。
功能说明
fscanf
函数从指定的输入流中读取数据,根据 format
字符串中的格式说明符对数据进行解析,并将解析后的数据存储到可变参数列表指定的变量中。它会跳过输入流中的空白字符(如空格、制表符、换行符等),直到遇到匹配 format
字符串的内容。
6.格式化输出函数 fprintf
int fprintf(FILE *stream, const char *format, ...);
参数说明
stream
:这是一个指向FILE
类型对象的指针,代表着要进行写入操作的输出流。该输出流可以是通过fopen
函数打开的文件流,也可以是标准输出流stdout
(即向屏幕输出数据)或者标准错误流stderr
(用于输出错误信息)。format
:这是格式控制字符串,它规定了输出数据的格式。format
字符串里可以包含普通字符和格式说明符。普通字符会原样输出,而格式说明符则用于指定要输出的数据的类型和格式,常见的格式说明符有:%d
:用于输出十进制整数。%f
:用于输出浮点数。%s
:用于输出字符串。%c
:用于输出单个字符。
...
:这是可变参数列表,包含了要按照format
字符串指定的格式输出的数据。参数的数量和类型要与format
字符串中的格式说明符一一对应。
功能说明
fprintf
函数会依据 format
字符串的格式要求,将可变参数列表中的数据格式化后写入到指定的输出流中。它可以将不同类型的数据以特定的格式组合成一个字符串,并输出到文件或屏幕等输出流。
返回值
- 成功写入的字符数量:若数据成功写入输出流,
fprintf
函数会返回实际写入的字符数量。 - 负值:若在写入过程中发生错误,函数会返回一个负值。
7.二进制写入函数 fwrite
size_t fread(void *ptr, size_t size, size_t count, FILE *stream);
参数说明
ptr
:这是一个指向用于存储读取数据的内存块的指针。该内存块的大小必须足够容纳要读取的数据。通常,它是一个数组或动态分配的内存空间。size
:每个数据项的大小(以字节为单位)。例如,如果你要读取整数,size
可以设置为sizeof(int)
;如果读取字符,size
则为sizeof(char)
。count
:要读取的数据项的数量。fread
函数会尝试读取count
个大小为size
字节的数据项。stream
:指向FILE
类型对象的指针,代表要从中读取数据的文件流。该文件流通常是通过fopen
函数以二进制读取模式(如"rb"
)打开文件得到的。
返回值
- 成功读取的数据项数量:
fread
函数返回实际成功读取的数据项数量。这个数量可能小于count
,原因可能是到达文件末尾或者在读取过程中发生错误。 - 若在读取开始前就遇到文件末尾或发生错误:返回 0。
功能说明
fread
函数的主要功能是从指定的文件流中读取二进制数据,并将其存储到 ptr
所指向的内存块中。它会尝试读取 count
个大小为 size
字节的数据项,但实际读取的数量可能会因为文件结束或错误而少于 count
。
8.二进制读取函数 fread
size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);
参数说明
ptr
:这是一个指向要写入数据的内存块的指针。该内存块里存储着准备写入文件的数据。size
:每个数据项的大小(以字节为单位)。比如,若要写入整数,size
可以设为sizeof(int)
;若写入字符,size
则为sizeof(char)
。count
:要写入的数据项的数量。fwrite
函数会尝试把count
个大小为size
字节的数据项写入文件。stream
:指向FILE
类型对象的指针,代表要写入数据的文件流。该文件流通常是通过fopen
函数以二进制写入模式(如"wb"
)打开文件得到的。
返回值
- 成功写入的数据项数量:
fwrite
函数返回实际成功写入的数据项数量。这个数量可能小于count
,这可能是因为写入过程中发生了错误。 - 若在写入开始前就发生错误:返回 0。
功能说明
fwrite
函数的主要功能是把 ptr
所指向的内存块中的二进制数据写入到指定的文件流中。它会尝试写入 count
个大小为 size
字节的数据项,但实际写入的数量可能会因错误而少于 count
。
注意事项
- 在使用文件操作函数时,要先使用
fopen
打开文件,并检查返回值是否为NULL
,以确保文件成功打开。 - 完成文件操作后,使用
fclose
关闭文件,防止资源泄漏。 - 二进制文件操作时,要使用
"rb"
或"wb"
模式打开文件。
三、调整文件指针
1.fseek
函数:
fseek
函数的主要功能是调整文件指针的位置
int fseek(FILE *stream, long int offset, int whence);
参数
stream
:指向FILE
对象的指针,此对象代表着要操作的文件流。该文件流是通过fopen
函数打开文件后得到的。offset
:这是一个长整型数值,它表示相对于whence
指定位置的偏移量,单位为字节。正数代表向文件末尾方向偏移,负数代表向文件开头方向偏移。whence
:它规定了偏移的起始位置,其取值有以下三种:SEEK_SET
:代表文件的起始位置。SEEK_CUR
:代表文件指针当前的位置。SEEK_END
:代表文件的末尾位置。
返回值
- 若文件指针位置调整成功,函数返回 0。
- 若出现错误,函数返回非零值。
功能说明
fseek
函数的作用是把文件指针移动到指定的位置,这样就能在文件的任意位置进行读写操作,这在处理需要随机访问的文件时非常有用。
2.ftell函数:
ftell函数能够帮助你获取文件指针在文件流里的当前位置
long int ftell(FILE *stream);
参数
stream
:指向FILE
对象的指针,该对象代表你要操作的文件流。这个文件流通常是通过fopen
函数打开文件后得到的。
返回值
- 若操作成功,
ftell
会返回当前文件指针相对于文件开头的偏移量,单位是字节。返回值类型为long int
。 - 若操作过程中出现错误,函数会返回
-1L
,并且会设置errno
来表明具体的错误类型。
功能说明
ftell
函数的主要功能是返回文件指针当前所在的位置,也就是从文件开头到当前位置的字节数。这在需要记录文件读取或写入位置,或者进行文件的随机访问时非常有用。例如,你可以结合 fseek
函数,先使用 ftell
记录当前位置,然后移动文件指针进行其他操作,最后再用 fseek
回到之前记录的位置。
3.rewind函数:
rewind函数是把文件指针重置到文件的起始位置
void rewind(FILE *stream);
参数
stream
:指向FILE
对象的指针,该对象代表着要操作的文件流。这个文件流一般是通过fopen
函数打开文件后得到的。
返回值
rewind
函数没有返回值,其返回类型为 void
。
功能说明
rewind
函数的主要功能是将指定文件流的文件指针移回到文件的开头。同时,它还会清除文件流的错误标志和文件结束标志(EOF
标志)。这意味着在调用 rewind
之后,你可以重新从文件的起始处开始读取或写入数据。
四、文件结束和错误情况
1.EOF
定义
EOF
是一个宏,通常在 <stdio.h>
头文件中被定义,其值一般为 -1。它代表 “End Of File”,即文件结束符。在文件操作里,EOF
用于表示已经到达文件的末尾。
用途
- 输入函数返回值判断:许多输入函数(如
fgetc
、fscanf
等)在遇到文件结束时会返回EOF
。通过检查这些函数的返回值是否为EOF
,可以判断是否已经读取到文件末尾。
2.feof
函数
int feof(FILE *stream);
参数
stream
:指向FILE
对象的指针,代表要检查的文件流。
返回值
- 如果文件流已经到达文件末尾,返回非零值(通常为 1)。
- 如果文件流尚未到达文件末尾,返回 0。
用途
feof
函数用于检查文件流是否已经到达文件末尾。需要注意的是,feof
函数只有在尝试读取操作后才会正确反映文件是否结束,也就是说,它是在读取操作遇到文件结束后才会返回非零值。
3.ferror
函数
int ferror(FILE *stream);
参数
stream
:指向FILE
对象的指针,代表要检查的文件流。
返回值
- 如果文件流在操作过程中发生错误,返回非零值(通常为 1)。
- 如果文件流没有发生错误,返回 0。
用途
ferror
函数用于检查文件流在操作过程中是否发生了错误。当文件操作(如读取、写入等)出现错误时,可以使用 ferror
函数来检测。