目录
1. 为什么使用文件
运行程序,数据放入内存,程序结束内存还给操作系统,为了数据的持久化保存,有了文件的概念
2. 关于文件
2.1程序文件
包括源程序文件(后缀为 .c ),目标文件(windows环境后缀为 .obj ),可执行程序(windows环境后缀为 .exe )。(简单来说就是自己写的代码)
2.2数据文件
文件的内容不一定是程序,而是程序运行时读写的数据,比如程序运行需要从中读取数据的文件,
或者输出内容的文件。
2.3 文件名
文件名包括:文件路径 + 文件名主干+ 文件后缀
- e.g.
c:\Code\test.txt
3. 文件的打开和关闭
3.1 文件指针
通过文件指针变量能够找到与它关联的文件。
FILE* pf;//文件指针变量
3.2 文件的打开与关闭
文件操作:
打开文件 fopen()→ (判断是否打开成功) → 读文件/写文件 → 关闭文件fclose() → 文件指针置空
-
fopen函数介绍
:
#include <stdio.h>
FILE * fopen ( const char * filename, const char * mode );
FILE * fopen ( “文件名” , “打开方式” );
-
关于mode打开方式:
“r”(只读)——为了输入数据,打开一个已经存在的文本文件
“w”(只写)—— 为了输出数据,打开一个文本文件
“a”(追加)——向文本文件尾添加数据
“r+”(读写)——为了读和写,打开一个文本文件
“w+”(读写)——为了读和写,建议一个新的文件
“a+”(读写)——打开一个文件,在文件尾进行读写With the mode specifiers above the file is open as a text file(文本文件). In order to open a file as a binary file(二进制文件), a “b” character has to be included in the mode string.
i.e: “rb”, “wb”, “ab”, “r+b”, “w+b”, “a+b”) or (“rb+”, “wb+”, “ab+”).
-
关于返回值:成功 return 指向 FILE 对象的指针。否则,return NULL。
-
fopen的使用
4. 文件的顺序读写
4.1 fputc
-
fputc
字符输出函数–写文件(写入单个字符)
fputc example
👇
/* fputc example: alphabet writer */
#include <stdio.h>
int main()
{
FILE* pFile = fopen("Alphabet.txt", "w");
char c = 0;
if (pFile != NULL)
{
for (c = 'A'; c <= 'Z'; c++)
{
fputc(c, pFile);
}
fclose(pFile);
pFile = NULL;
}
return 0;
}
4.2 fgetc
-
fgetc
字符输入函数–读文件(读单个字符)
fgetc example
👇
/* fgetc example: money counter */
#include <stdio.h>
int main()
{
FILE* pFile = fopen("Myfile.txt", "r");
int c = 0, n = 0;
if (NULL == pFile)
perror("Error Opening File");
else
{
do
{
c = fgetc(pFile);
if (c == '$')
{
n++;
}
} while (c != EOF);
fclose(pFile);
pFile = NULL;
printf("The File Contains %d Dollar Sign Characters ($).\n", n);
}
return 0;
}
4.3 fputs
-
fputs
文本行输出函数–写文件(一行一行地写入)
该函数从指定的地址 (str) 开始复制,直到到达终止空字符 (‘\0’)。此终止空字符不会复制到流中。
请注意,fput 与 put 的不同之处不仅在于可以指定destination stream,而且 fput 不会写入其他字符,而 put 会自动在末尾附加换行符。
fputs example
👇
/* fputs example */
#include <stdio.h>
int main()
{
FILE* pFile = fopen("Mylog.txt", "w");
if (pFile != NULL)
{
fputs("Enter Sentence To Append: ", pFile);
fputs("NOTHING", pFile);
fclose(pFile);
pFile = NULL;
}
return 0;
}
4.4 fgets
-
fgets
文本行输入函数(一行一行地读)
- 从 stream 中读取字符并将其作为 C 字符串存储到 str 中,直到读取 (num-1) 个字符或到达换行符或文件末尾,以先发生者为准。
- 换行符使 fgets 停止读取,但它被函数视为有效字符,并包含在复制到 str 的字符串中。终止空字符会自动附加到复制到 str 的字符之后。
- 请注意,fgets 与 get 完全不同:fgets 不仅接受stream参数,还允许指定 str 的最大大小,并在字符串中包含任何结束换行符。
fgets example
👇
/* fgets example */
#include <stdio.h>
int main()
{
//打开文件
FILE* pFile = fopen("Myfile.txt", "r");
if (pFile == NULL)
{
perror("Error Opening File");
return 1;
}
//读文件
char arr[] = "########";
fgets(arr, 5, pFile);
//关闭文件
fclose(pFile);
pFile = NULL;
return 0;
}
- 多次使用fgets呢?
4.5 fprintf
4.6 fscanf
4.7 fwrite
4.8 fread
⭐sum.
注:关于方向的问题👉这里输入(读)入是指入内存,输出(写)是指出内存。
对比一组函数:
scanf/fscanf/sscanf
printf/fprintf/sprintf
scanf
: 按一定格式从键盘输入数据
printf
: 按一定格式向屏幕输出数据
👆适用于标准流的格式化输入输出语句
注:键盘stdin——标准输入流;屏幕stout——(标准输出流).
#include <stdio.h>
int scanf ( const char * format, ... );
int printf ( const char * format, ... );
fscanf
: 按一定格式从输入流(文件/stdin)输入数据
fprintf
: 按一定格式向输出流(文件/stout)输出数据
👆适用于所有流的格式化输入输出语句
#include <stdio.h>
int fprintf ( FILE * stream, const char * format, ... );
int fscanf ( FILE * stream, const char * format, ... );
sscanf
: 按一定格式从string中输入(读)数据
sprintf
: 按一定格式向string输出(写)数据
#include <stdio.h>
int sscanf ( const char * s, const char * format, ...);
int sprintf ( char * str, const char * format, ... );
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s = { "Fantasy",13,77.3f };
struct S tmp = { 0 };
char buf[100] = { 0 };
//把struct中信息按一定格式写入buf数组
sprintf(buf, "%s %d %f", s.name, s.age, s.score);
printf("%s\n", buf);
//能否将buf中的字符串还原?→sscanf
sscanf(buf, "%s %d %f", tmp.name, &(tmp.age), &(tmp.score));
printf("%s %d %f\n", tmp.name, tmp.age, tmp.score);
return 0;
}
/* example */
#include <stdio.h>
int main()
{
char str[80];
float f;
FILE* pFile = fopen("Myfile.txt", "w+");
if (pFile == NULL)
{
perror("Error Opening File");
return 1;
}
fprintf(pFile, "%f %s", 3.1416, "hello");
rewind(pFile);//将pFile所指向的位置 置为--初始位置
fscanf(pFile, "%f", &f);
fscanf(pFile, "%s", str);
fclose(pFile);
pFile = NULL;
printf("I have read: %f and %s \n", f, str);
return 0;
}
👉应用——通讯录的改造
【C语言进阶】[文件操作应用]——文件版通讯录contact3.0
5. 文件的随机读写
5.1 fseek
根据文件指针的位置和偏移量来定位文件指针。
三个参数:(
文件指针
,偏移多少量
(正数向后偏移;负数向前偏移),从哪里开始偏移
)
int fseek ( FILE * stream, long int offset, int origin );
int origin参数的三个选择👇
/* fseek example */
#include <stdio.h>
int main()
{
FILE* pFile = fopen("example.txt", "r");
if (pFile == NULL)
{
perror("Error Opening File");
return 1;
}
//按顺序
fgetc(pFile);//读a,指针指向b
printf("%c\n", fgetc(pFile));//读到b,指针指向c
//随机读
fseek(pFile, 2, SEEK_CUR);//指针向后偏移两个位置c→d→e,读到e,指针指向f
printf("fseek:%c\n", fgetc(pFile));//e
printf("%c\n", fgetc(pFile));//f
fclose(pFile);
pFile = NULL;
return 0;
}
5.2 ftell
返回文件指针相对于起始位置的偏移量
long int ftell ( FILE * stream );
5.3 rewind
让文件指针的位置回到文件的起始位置
void rewind ( FILE * stream );
6. 文本文件和二进制文件
数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。
如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式(字符对应的ASCII码值) 存储的文件就是 文本文件。
7. 文件读取结束的判定
feof
feof
:判断文件为什么结束
- 文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:
- fgetc 判断是否为 EOF .
- fgets 判断返回值是否为 NULL .
- 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数。
例如:
- fread判断返回值是否小于实际要读的个数
8. 文件缓冲区
关闭文件会自动刷新
因为有缓冲区的存在,C语言在操作文件的时候,需要做刷新缓冲区或者在文件操作结束的时候关闭文件。
如果不做,可能导致读写文件的问题
————————————————————————————————————@fantasy_13_7———EDN————————