一.文件指针
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结构体的地址交给指针
- 实际由库函数通过指针操作文件
(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_SET
、SEEK_CUR
或SEEK_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;
}
1 条评论
博主真是太厉害了!!!