1.什么是文件
磁盘上的文件是文件。
但是在程序设计中,我们一般谈的文件有两种:程序文件、数据文件(从文件功能的角度来分类的)。
程序文件
包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows环境
后缀为.exe)。
数据文件
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,
或者输出内容的文件。
本章讨论的是数据文件。
在以前各章所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显
示器上。
其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理
的就是磁盘上文件。
2.文件的打开与使用
1.文件指针
(此次博文以vs2013示例 )
在vs2013中,有这么一份代码
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
typedef struct _iobuf FILE;
该代码是由vs自行提供的,主要目的是方便用户的使用
每当打开一个文件的时候,系统会根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,
使用者不必关心细节。
一般都是通过一个FILE的指针来维护这个FILE结构的变量,。所以当我们们想要读写一个文件时,可以很好的来使用它。下面我们用一串代码实现读文件,而打开文件有着多种操作命令,我们先来认识一下。
- “r”(只读): 为了输入数据,打开一个已经存在的文本文件。如果文件不存在,则会出错。
- “w”(只写): 为了输出数据,打开一个文本文件。如果文件不存在,则会创建一个新的文件。
- “a”(追加): 向文本文件尾添加数据。如果文件不存在,则会创建一个新的文件。
- “rb”(只读): 为了输入数据,打开一个二进制文件。如果文件不存在,则会出错。
- “wb”(只写): 为了输出数据,打开一个二进制文件。如果文件不存在,则会创建一个新的文件。
- “ab”(追加): 向一个二进制文件尾添加数据。如果文件不存在,则会创建一个新的文件。
- “r+”(读写): 为了读和写,打开一个文本文件。如果文件不存在,则会出错。
- “w+”(读写): 为了读和写,建议一个新的文件。如果文件不存在,则会创建一个新的文件。
- “a+”(读写): 打开一个文件,在文件尾进行读写。如果文件不存在,则会创建一个新的文件。
- “rb+”(读写): 为了读和写打开一个二进制文件。如果文件不存在,则会出错。
- “wb+”(读写): 为了读和写,新建一个新的二进制文件。如果文件不存在,则会创建一个新的文件。
- “ab+”(读写): 打开一个二进制文件,在文件尾进行读和写。如果文件不存在,则会创建一个新的文件。
2.1文件的打开与关闭
掌握了文件的打开与关闭后,我们就可以用指令来完成一些简单的文件操作了
3.文件的读与写
函数名称 | 适用流 |
---|---|
fgetc | 所有输入流 |
fputc | 所有输出流 |
fgets | 所有输入流 |
fputs | 所有输出流 |
fscanf | 所有输入流 |
fprintf | 所有输出流 |
3.1 fgetc与fputc
*int fgetc(FILE stream)
参数
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了要在上面执行操作的流。
返回值
该函数以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生读错误,则返回 EOF。
*int fputc(int char, FILE stream)
参数
char – 这是要被写入的字符。该字符以其对应的 int 值进行传递。
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符的流。
返回值
如果没有发生错误,则返回被写入的字符。如果发生错误,则返回 EOF,并设置错误标识符。
代码实现
int main()
{
FILE* file = fopen("file.txt", "wb");//打开一个文件,以二进制输出的方式打开;
if (file == NULL)//判断文件指针是否接收成功
{
perror("file");
return;
}
for (int i = 'a'; i <= 'z'; i++)//循环写入
{
fputc(i, file);
}
fclose(file);//关闭文件
file = NULL;//释放内存
return 0;
}
当完成代码写入后,我们的项目文件下就会多一个自行创建的文件夹,切内容为字符a开始,字符z结尾;
int main()
{
FILE* file = fopen("file.txt", "rb");//打开一个文件,以二进制输入的方式打开;
if (file == NULL)//判断文件指针是否接收成功
{
perror("file");
return;
}
char arr;
for (int i = 0; i < 32; i++)//循环输入
{
arr =fgetc(file);
printf("%c ", arr);
}
fclose(file);//关闭文件
file = NULL;//释放内存
return 0;
}
输入结果
3.2fgets与fputs
**char *fgets(char str, int n, FILE stream)
参数
str – 这是指向一个字符数组的指针,该数组存储了要读取的字符串。
n – 这是要读取的最大字符数(包括最后的空字符)。通常是使用以 str 传递的数组长度。
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了要从中读取字符的流。
返回值
如果成功,该函数返回相同的 str 参数。如果到达文件末尾或者没有读取到任何字符,str 的内容保持不变,并返回一个空指针。
如果发生错误,返回一个空指针。
**int fputs(const char str, FILE stream)
参数
str – 这是一个数组,包含了要写入的以空字符终止的字符序列。
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了要被写入字符串的流。
返回值
该函数返回一个非负值,如果发生错误则返回 EOF。
代码实现
fputs与fputc的差别就在于一个一次输出一串字符,一个一次输出一个字符
int main()
{
FILE* file = fopen("file.txt", "wb");//打开一个文件,以二进制输入的方式打开;
if (file == NULL)//判断文件指针是否接收成功
{
perror("file");
return;
}
fputs("hello,world", file);//输出字符
fclose(file);//关闭文件
file = NULL;//释放内存
return 0;
}
接下来使用fgtes输入
int main()
{
FILE* file = fopen("file.txt", "rb");//打开一个文件,以二进制输入的方式打开;
if (file == NULL)//判断文件指针是否接收成功
{
perror("file");
return;
}
char arr[20];//创建数组接收从文件中输入的字符串
int len = strlen("hello,world");
fgets(arr,len+1, file);//输入字符串,fgtes的特性会导致'\0'也算一个字符,所以+1;
printf("%s", arr);//打印
fclose(file);//关闭文件
file = NULL;//释放内存
return 0;
}
3.3fprintf与fscanf
**int fprintf(FILE stream, const char format, …)
参数
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
format – 这是 C 字符串,包含了要被写入到流 stream 中的文本。它可以包含嵌入的 format 标签,format 标签可被随后的附加参数中指定的值替换,并按需求进行格式化
返回值
如果成功,则返回写入的字符总数,否则返回一个负数。
**int fscanf(FILE stream, const char format, …)
参数
stream – 这是指向 FILE 对象的指针,该 FILE 对象标识了流。
format – 这是 C 字符串,包含了以下各项中的一个或多个:空格字符、非空格字符 和 format 说明符。
返回值
如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF。
struct s//定义一个结构体
{
char arr[10];
int b;
char c[10];
};
int main()
{
FILE* file = fopen("file.txt", "wb");//打开一个文件,以二进制输入的方式打开;
if (file == NULL)//判断文件指针是否接收成功
{
perror("file");
return;
}
struct s i = { 'a',100,'c' };//结构体初始化
fprintf(file, "%s %d %s", i.arr, i.b, i.c);//输出到文件中
fclose(file);//关闭文件
file = NULL;//释放内存
return 0;
}
运行结果
struct s//定义一个结构体
{
char arr[10];
int b;
char c[10];
};
int main()
{
FILE* file = fopen("file.txt", "rb");//打开一个文件,以二进制输入的方式打开;
if (file == NULL)//判断文件指针是否接收成功
{
perror("file");
return;
}
struct s i = { 0 };//结构体初始化
fscanf(file, "%s %d %s", i.arr, &(i.b), i.c);
printf("%s %d %s", i.arr, i.b, i.c);
fclose(file);
file = NULL;//释放内存
return 0;
}
fprintf和fscanf的输出输入是多样的,只要你传递给他正确的格式即可
谢谢观看。