C语言文件操作
C语言中,通过FILE*的文件指针来维护流的各种操作
文件的打开和关闭
文件指针
缓冲⽂件系统中,关键的概念是“⽂件类型指针”,简称“⽂件指针”。
每个被使⽤的⽂件都在内存中开辟了⼀个相应的⽂件信息区,⽤来存放⽂件的相关信息(如⽂件的名
字,⽂件状态及⽂件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系
统声明的,取名FILE。
例如创建一个文件指针
FILE* pf;
定义pf是⼀个指向FILE类型数据的指针变量。可以使pf指向某个⽂件的⽂件信息区(是⼀个结构体变量)。通过该⽂件信息区中的信息就能够访问该⽂件。也就是说,通过⽂件指针变量能够间接找到与它关联的⽂件。
文件的打开和关闭
⽂件在读写之前应该先打开⽂件,在使⽤结束之后应该关闭⽂件。
在编写程序的时候,在打开⽂件的同时,都会返回⼀个FILE*的指针变量指向该⽂件,也相当于建⽴了
指针和⽂件的关系。
ANSI C 规定使⽤ fopen 函数来打开⽂件, fclose 来关闭⽂件。
//打开文件
FILE* fopen ( const char* filename, const char* mode);
//关闭文件
int fclose ( FILE* stream);
filename表示文件名
mode表示文件的打开方式,下面都是文件的打开方式
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "w");
if ( !pf )
{
perror("fopen");
return 1;
}
fclose(pf);
pf = NULL;
return 0;
}
文件的顺序读写
fgetc与fputc的使用
//写文件--fputc
//int fputc ( int character, FILE * stream );
int main()
{
FILE* pf = fopen("test.txt", "w");
if (!pf)
{
perror("fopen");
return 1;
}
//写文件
/*fputc('a', pf);
fputc('b', pf);
fputc('c', pf);*/
char ch = 0;
for (ch = 'a'; ch <= 'z'; ch++)
{
fputc(ch, pf);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
//读文件--fgetc
//int fgetc ( FILE * stream );
int main()
{
FILE* pf = fopen("test.txt", "r");
if (!pf)
{
perror("fopen");
return 1;
}
//写文件
//如果成功读取字符的话,返回的是字符的ASCII码值-char
//如果读取遇到文件末尾,或者读取失败的时候,返回EOF(-1)
char c = 0;
while ((c = fgetc(pf)) != EOF)
{
printf("%c", c);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fgets与fputs的使用
//写文件--fputs
//int fputs ( const char * str, FILE * stream );
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "w");
if (!pf)
{
perror("fopen");
return 1;
}
//写文件
fputs("hello world\n", pf);
fputs("hello bit\n", pf);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
//读文件--fgets
//char * fgets ( char * str, int num, FILE * stream );
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (!pf)
{
perror("fopen");
return 1;
}
//读文件
//char * fgets ( char * str, int num, FILE * stream );
//只读num - 1个数据、最后一个放\0
//读取成功返回str
//读取错误返回NULL
char ch[20] = { 0 };
while (fgets(ch, 20, pf) != NULL)
{
printf("%s", ch);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fscanf与fprintf的使用
//写文件--fprintf
//int fprintf ( FILE * stream, const char * format, ... );
struct S
{
char name[20];
int age;
float score;
};
int main()
{
struct S s = { "哈哈",18,65.5f};
//打开文件
FILE* pf = fopen("test.txt", "w");
if (!pf)
{
perror("fopen");
return 1;
}
//写文件 - 是以文本的形式写进去的
//int fprintf ( FILE * stream, const char * format, ... );
fprintf(pf, "%s %d %f", s.name, s.age, s.score);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
struct S
{
char name[20];
int age;
float score;
};
//读文件--fscanf
//int fscanf ( FILE * stream, const char * format, ... );
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (!pf)
{
perror("fopen");
return 1;
}
struct S s = { 0 };
//读文件
//从文件test.txt中读取数据放到s中
//int fscanf ( FILE * stream, const char * format, ... );
fscanf(pf, "%s %d %f", s.name, &s.age, &s.score);
//打印在屏幕上
printf("%s %d %f\n", s.name, s.age, s.score);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
fread与fwrite的使用
//写文件--fwrite
//size_t fwrite(const void* ptr, size_t size, size_t count, FILE * stream);
int main()
{
int arr[] = { 1,2,3,4,5 };
//打开文件
FILE* pf = fopen("test.txt", "wb");
if (!pf)
{
perror("fopen");
return 1;
}
//写文件
int sz = sizeof(arr) / sizeof(arr[0]);
fwrite(arr, sizeof(arr[0]), sz, pf);//以二进制的形式写进去
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
//写文件--fread
//size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
int main()
{
int arr[5] = { 0 };
//打开文件
FILE* pf = fopen("test.txt", "rb");
if (!pf)
{
perror("fopen");
return 1;
}
//读文件
//size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
//读二进制文本
int i = 0;
while (fread(&arr[i], sizeof(arr[0]), 1, pf))
{
printf("%d ", arr[i++]);
}
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
文件的随机读写
1.fseek :根据⽂件指针的位置和偏移量来定位⽂件指针。
int fseek (FILE* stream, long int offset, int origin);
offset:距离origin偏移量
origin:
- SEEK_SET:光标起始位置.
- SEEK_CUR:光标当前位置.
- SEEK_END:光标末端位置.
2.ftell:返回文件指针相对于起始位置的偏移量
long int ftell ( FILE* stream);
3.rewind:让文件指针的位置回到文件的起始位置
void rewind ( FILE* stream);
文件的随机读写
int main()
{
//打开文件
FILE* pf = fopen("test.txt", "r");
if (!pf)
{
perror("fopen");
return 1;
}
//读文件
//fseek
char ch = fgetc(pf);
printf("%c\n", ch);
fseek(pf, 4, SEEK_CUR);//文件当前位置
ch = fgetc(pf);
printf("%c\n", ch);
fseek(pf, 5, SEEK_SET);//文件起始位置
ch = fgetc(pf);
printf("%c\n", ch);
fseek(pf, -4, SEEK_END);//文件结束位置
ch = fgetc(pf);
printf("%c\n", ch);
//ftell--返回文件指针相对起始位置的偏移量
fseek(pf, 0, SEEK_END);
printf("%d\n", ftell(pf));
//rewind--让文件指针回到文件的其实位置
rewind(pf);
ch = fgetc(pf);
printf("%c\n", ch);
//关闭文件
fclose(pf);
pf = NULL;
return 0;
}
文件读取结束的判断
在⽂件读取过程中,不能⽤feof函数的返回值直接来判断⽂件的是否结束。
feof 的作⽤是:当⽂件读取结束的时候,判断读取结束的原因是否是:遇到⽂件尾结束。
- ⽂本⽂件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets )
例如:
• fgetc 判断是否为 EOF .
• fgets 判断返回值是否为 NULL . - ⼆进制⽂件的读取结束判断,判断返回值是否⼩于实际要读的个数。
int main()
{
FILE* pf = fopen("test.txt", "r");
if (!pf)
return 1;
char ch = 0;
while ((ch = fgetc(pf) != EOF))
{
printf("%c ", ch);
}
//判断是什么原因结束的
if (feof(pf))
printf("遇到文件末尾,读取正常结束\n");
else if (ferror(pf))
perror("fgetc");
return 0;
}
文件拷贝
拷贝文件:test1.txt--->test2.txt
int main()
{
FILE* pfin = fopen("test1.txt", "r");
if (!pfin) {
perror("fopen:test1.txt");
return 1;
}
FILE* pfout = fopen("test2.txt", "w");
if (!pfout) {
fclose(pfin);
perror("fopen:test2.txt");
return 1;
}
//读文件和写文件
int ch = 0;
while ((ch = fgetc(pfin)) != EOF)
{
fputc(ch, pfout);
}
fclose(pfin);
pfin = NULL;
fclose(pfout);
pfout = NULL;
return 0;
}