C语言文件操作
1. 为什么使用文件
为了使数据更长久的储存。
2. 什么是文件
文件包括程序文件和数据文件
程序文件:源文件,目标文件,可执行文件
数据文件:程序运行过程中可以进行读写的文件。
文件名包括3部分:文件路径,文件名和文件后缀。
3. 文件的打开和关闭
文件指针
每个文件在打开的时候,都会开辟一个文件信息区。这个文件信息区的类型为
FILE
类型,对于读写都是通过FILE
指针来实现的。
文件的打开和关闭
需要的头文件为
stdio.h
,文件打开后,等到不使用它的时候,不要忘记关闭文件。
fopen
第一个参数为文件系统名,第二个参数为文件访问的模式
访问模式如下:
返回类型为FILE*
。文件访问成功返回指向新文件流的指针。失败返回空指针。
fclose
关闭文件,参数为
FILE*
类型的流。返回类型为int
有没有发现这个函数和free
相似。
简单的使用一下
int main()
{
FILE* p = fopen("test.txt", "w");
if (p == NULL)
{
perror("fopen");
return 0;
}
fclose(p);
p = NULL;
return 0;
}
int main()
{
FILE* p = fopen("test.txt", "r");
if (p == NULL)
{
perror("fopen");
return 0;
}
fclose(p);
p = NULL;
return 0;
}
4. 文件的顺序读写
fgetc
参数为
FILE*
的流,成功时为作为unsigned char
获得并转换为int
的字符,失败时为EOF
。
例:
int main()
{
FILE* p = fopen("test.txt", "r");
if (p == NULL)
{
perror("fopen");
return 0;
}
int ch;
while ((ch=fgetc(p))!=EOF)
{
printf("%c", ch);
}
fclose(p);
p = NULL;
return 0;
}
fputc
写入字符
ch
到给定输出流stream
成功时,返回被写入字符。失败时,返回EOF
例:
int main()
{
FILE* p = fopen("test.txt", "w");
if (p == NULL)
{
perror("fopen");
return 0;
}
char ch;
for (ch = 'a'; ch <= 'z'; ch++)
{
fputc(ch, p);
}
fclose(p);
p = NULL;
return 0;
}
fgets
从
stream
流中最多获得n-1
个字符到string
中。遇到换行符\n
或者是文件结束时停止分析。并返回srting
。若没有读取字符,返回空指针,不覆盖string
指向字符串的内容。
例:
int main()
{
FILE* p = fopen("test.txt", "r");
if (p == NULL)
{
perror("fopen");
return 0;
}
char arr[200]={0};
while (fgets(arr, 200, p))
{
printf("%s", arr);
}
fclose(p);
p = NULL;
return 0;
}
fputs
把字符串写入
stream
中
成功时,返回非负值。失败时,返回EOF
例:
int main()
{
FILE* p = fopen("test.txt", "w");
if (p == NULL)
{
perror("fopen");
return 0;
}
fputs("acd", p);
fclose(p);
p = NULL;
return 0;
}
fscanf
从文件流 stream 读取数据。
返回值和scanf
的返回方式一样。
例:
int main()
{
FILE* p = fopen("test.txt", "r");
if (p == NULL)
{
perror("fopen");
return 0;
}
char arr[200] = { 0 };
fscanf(p,"%s",arr);
printf("%s\n", arr);
fclose(p);
p = NULL;
return 0;
}
fprintf
写结果到文件流
stream
用法和printf
的用法非常相似。
int main()
{
FILE* p = fopen("test.txt", "w");
if (p == NULL)
{
perror("fopen");
return 0;
}
fprintf(p, "%s", "哈哈哈");
fclose(p);
p = NULL;
return 0;
}
fread
把流中的数据读入到数组中
size
为每个对象字节的大小
count
要读取的对象的个数。
例:
int main()
{
FILE* p = fopen("test.txt", "r");
if (p == NULL)
{
perror("fopen");
return 0;
}
char arr[200]={0};
fread(arr, 1, 100, p);
printf("%s\n", arr);
fclose(p);
p = NULL;
return 0;
}
fwrite
把
buffer
指向里面的数据写到stream
流中
size
是一个对象的大小,count
为对象的个数
例:
int main()
{
FILE* p = fopen("test.txt", "w");
if (p == NULL)
{
perror("fopen");
return 0;
}
char arr[200] = "abcdefds";
fwrite(arr, 1, 20, p);
fclose(p);
p = NULL;
return 0;
}
sscanf
格式化读入
从buffer
中的数据读入到后面的格式化中
例:
struct s
{
int age;
char name[30];
};
int main()
{
struct s a;
char arr[100]="20zhangsan";
sscanf(arr, "%d %s", &(a.age), a.name);
return 0;
}
sprintf
格式化写入
把格式化的数据写入到字符串中
例:
struct s
{
int age;
char name[30];
};
int main()
{
struct s a={20,"zhangsan"};
char arr[100] = { 0 };
sprintf(arr, "%d %s", a.age, a.name);
return 0;
}
5. 文件的随机读写
fseek
设置文件流 stream 的文件位置指示器的指向
关于返回值,成功返回0,否则返回非零。
例:
int main()
{
FILE* p = fopen("test.txt", "w");
if (p == NULL)
{
perror("fopen");
return 0;
}
fputs("sscbcsd", p);
fseek(p, 2, SEEK_SET);
fputs("哈哈", p);
fclose(p);
p = NULL;
return 0;
}
ftell
例:
int main()
{
FILE* p = fopen("test.txt", "wb");
if (p == NULL)
{
perror("fopen");
return 0;
}
fseek(p, 2, SEEK_SET);
long ret=ftell(p);
printf("%d\n", ret);
fclose(p);
p = NULL;
return 0;
}
rewind
例:
int main()
{
FILE* p = fopen("test.txt", "wb");
if (p == NULL)
{
perror("fopen");
return 0;
}
fseek(p, 2, SEEK_SET);
rewind(p);
printf("%ld\n", ftell(p));
fclose(p);
p = NULL;
return 0;
}
6. 文本文件和二进制文件
数据在内存中是怎么储存,在文件中就是怎么储存,这就是二进制文件。
把内存的数据转换成ASCII形式存储,这种就是文本文件。
7. 文件读取结束的判定
下面两个函数分别判断文件是以那种方式结束的,是错误原因导致的还是文件读完结束的。
ferror
若文件流已出现错误则为非零值,否则为 0
feof
若已抵达流尾则为非零值,否则为 0
例:
int main()
{
FILE* p = fopen("test.txt", "wb");
if (p == NULL)
{
perror("fopen");
return 0;
}
fseek(p, 2, SEEK_SET);
rewind(p);
printf("%ld\n", ftell(p));
if (feof(p))
printf("文件没有读取完\n");
else if (ferror(p))
printf("文件读取错误\n");
fclose(p);
p = NULL;
return 0;
}
8. 文件缓冲区
无论是读还是写,都是从缓冲区中拿。