文件操作
- 一、文件的打开和关闭
- 二、文件的顺序读写
- fgetc和fputc
- fgets和fputs
- fscanf和fprintf
- sscanf和sprintf
- fread和fwrite
- 三、文件的随机读写
- 1.fseek
- 2.ftell
- 3.rewind
- 四、补充
- 1.文件读取结束的判定
- 2.文件缓冲区
一、文件的打开和关闭
流和标准流
流:想象为流淌着字符的河。
C语言程序在启动时,默认打开stdin\stdout\stderr这三个标准流。
文件指针:FIFE*
//打开文件
FIFE* fopen(const char* filename,const char* mode);
//关闭文件
int fclose(FIFE* stream);
mode表示文件的打开方式。
这里我只列举几种常见的方式:
文件使用方式 | 含义 |
---|---|
r:只读 | 为了输入数据,打开一个已经存在的文本文件 |
w:只写 | 为了输出数据,打开一个文本文件,若文件不存在则新建一个 |
a:追加 | 向文本文件尾添加数据 |
- 只读创建文件方式:
2.
3.
添加刚才的text.txt。
二、文件的顺序读写
下面说的所有输入流一般适用于标准输入流和其他输入流(如文件输入流);以此类推输出流。
注意:虽然按照我编写的顺序都是将输入(读)放在前面,但实际应用时应写写入数据创建文件后,才能成功读出数据。
fgetc和fputc
字符输入函数和输出函数,使用于所有输入/出流。
fputc:要写入的字符int提升。
int main()
{
FIFE* pf = fopen("test.txt","w");
if(pf == NULL)
{
perror("fopen");
return 1;
}
//写文件
char ch = 0;
for(ch='a';ch<='z';ch++)
{
fputc(ch,pf);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fgetc的返回值为int,当位于文件末尾或读取错误时会返回EOF(-1)。
//读文件
int ch = 0;
while((ch = fgetc(pf)) != EOF)
{
printf("%c",ch);
}
fgets和fputs
文本行输入/出函数,适用于所有输入/出流。
直到到达终止字符\0停止复制。
fputs("hello world\n",pf);//\n也会展现出来
fputs("hello!",pf);
换行符会使 fgets 停止读取,但它被函数视为有效字符,并包含在复制到 str 的字符串中。
//读文件
char arr[20] = {0};
while(fgets(arr,20,pf) != NULL)
{
printf("%s",arr);
}
这里num表示一次读取的最大字符数,注意即使小于字符串个数,相当于多读取几次但是获取的结果还是完整的。
fscanf和fprintf
格式化输入函数和输出函数,适用于所有输入/出流。
在format参数之后,该函数至少需要与format指定的相同数量的附加参数。
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s = { "张三", 20, 65.5f };
//想把s中的数据存放在文件中
FILE* pf = fopen("test.txt", "w");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写文件 - 是以文本的形式写进去的
fprintf(pf, "%s %d %f", s.name, s.age, s.score);
fclose(pf);
pf = NULL;
return 0;
}
fscanf(pf, "%s %d %f", s.name, &(s.age), &(s.score));
sscanf和sprintf
分别用于从字符串读取格式化的数据和将格式化的数据写入字符串,这两个函数不直接适用于文件流或标准输入/输出流(如 stdin 和 stdout),但可以用于处理字符串数据,这些字符串可以来源于文件读取或任何其他来源。
缓冲区的大小应该足够大,以包含整个结果字符串。
int main()
{
char buf[200] = { 0 };
struct S s = { "张三", 20, 65.5f };
sprintf(buf, "%s %d %f", s.name, s.age, s.score);
printf("1以字符串的形式: %s\n", buf);//1
struct S t = {0};
sscanf(buf, "%s %d %f", t.name, &(t.age), &(t.score));
printf("2按照格式打印 : %s %d %f\n", t.name, t.age, t.score);//2
return 0;
}
fread和fwrite
二进制输入、输出,适用于文件输入/出流。
返回成功写入的元素个数。
int main()
{
int arr[] = { 1,2,3,4,5 };
FILE*pf = fopen("test.txt", "wb");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//写数据
int sz = sizeof(arr) / sizeof(arr[0]);
fwrite(arr, sizeof(arr[0]), sz, pf);//以二进制的形式写进去的
fclose(pf);
pf = NULL;
return 0;
}
这时test.txt文件里的数据是看不懂的,因为是二进制文件,下面打印出来观察。
int main()
{
int arr[5] = { 0 };
FILE* pf = fopen("test.txt", "rb");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读数据-以二进制的形式写进去的
int i = 0;
while (fread(&arr[i], sizeof(int), 1, pf))//或用for循环逐个打印
{
printf("%d ", arr[i]);
i++;
}
fclose(pf);
pf = NULL;
return 0;
}
这样打印出1 2 3 4 5 正常。
三、文件的随机读写
1.fseek
根据文件指针的位置和偏移量来定位文件指针(文件内容的光标)。
int fseek ( FILE * stream, long int offset, int origin );
这里的origin有三种可能:分别是SEEK_SET(开始),SEEK_CUR(当前光标),SEEK_END(末尾)。
注:当从后先前移动光标时,偏移量为负数。
2.ftell
返回文件指针相对于起始位置的偏移量。
long int ftell ( FILE * stream );
eg:可用于求字符串长度等。
3.rewind
让文件指针的位置回到文件的起始位置。
void rewind ( FILE * stream );
eg:可用于不必记录直接回到指针起始位置等。
四、补充
1.文件读取结束的判定
feof,不能原来判断文件是否结束,作用:判断文件读取结束时,是否是因为遇到文件尾。
- 文本文件:
fgetc判断是否为EOF,fgets判断返回值是否为NULL。 - 二进制文件:
判断返回值是否小于实际要读的个数。
int main()
{
FILE* pf = fopen("test.txt", "r");
if (pf == NULL)
{
perror("fopen");
return 1;
}
//读取
int ch = 0;
while ((ch = fgetc(pf)) != EOF)
{
printf("%c\n", ch);
}
//判断是什么原因导致读取结束的
if (feof(pf))
{
printf("遇到文件末尾,读取正常结束\n");
}
else if (ferror(pf))
{
perror("fgetc");
}
return 0;
}
2.文件缓冲区
数据优先送到内存中的缓冲区,装满后一起送到磁盘上…
推荐学习网站,方便查找函数:链接: cpluscplus