一、文件编程
文件是指存储在计算机上的数据的集合,C语言中的文件编程是指使用C语言的标准库函数来对文件进行操作,如打开,关闭,读取,写入等。
Linux下文件类型分类:一切都是文件。
磁盘文件:数据的有序集合,存在外存里面。磁盘文件的分类:
1、文本文件:基于字符编码的文件 八位一个编码。
2、二进制文件:根据值编码。
设备文件:把所有的输入输出设备当成是文件:把对设备的数据的读写当成是文件的读写。文件操作
1、系统调用 :
2、库函数 :系统调用函数的封装,本质上一样,都是系统函数的调用
标准IO :stdio.h
缓冲区:减少系统调用的次数,提高系统运行效率
1、行缓冲 :遇到换行符就清空缓冲区
2、全缓冲 :塞满缓冲区再输出
3、无缓冲 : 直接调用系统IO口,不经过缓冲区
printf:
将缓冲区中的数据输出的方法:
1、换行符
2、程序结束也会清空
3、塞满缓冲区
4、刷新缓冲区 fflush 刷新缓冲区函数
scanf:
getchar():从终端获取一个字符
文件编程的基本步骤如下:
- 定义一个文件指针变量,用来指向要操作的文件。
- 调用`fopen`函数,以指定的模式打开文件,并将文件指针赋给文件指针变量。如果打开失败,返回`NULL`。
- 调用`fread`、`fwrite`、`fscanf`、`fprintf`、`fgets`、`fputs`等函数,根据需要对文件进行读写操作。
- 调用`fseek`、`ftell`、`rewind`等函数,根据需要对文件进行定位操作。
- 调用`fclose`函数,关闭文件,并释放文件指针变量。示例代码如下:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp1, *fp2; //定义两个文件指针变量
char ch; //定义一个字符变量,用来存储读取的字符
//以只读模式打开源文件
fp1 = fopen("source.txt", "r");
//判断是否打开成功
if (fp1 == NULL)
{
printf("打开源文件失败\n");
exit(1); //退出程序
}
//以写入模式打开目标文件
fp2 = fopen("target.txt", "w");
//判断是否打开成功
if (fp2 == NULL)
{
printf("打开目标文件失败\n");
exit(1); //退出程序
}
//循环读取源文件的每个字符,直到文件末尾
while ((ch = fgetc(fp1)) != EOF)
{
//将读取的字符写入目标文件
fputc(ch, fp2);
}
//关闭文件
fclose(fp1);
fclose(fp2);
printf("文件复制成功\n");
return 0;
}
二、文件编程中常用的函数
1、`fopen`函数:FILE *fopen(const char *__restrict__ __filename, const char *__restrict__ __modes)
用于打开一个文件,返回一个文件指针,如果打开失败,返回`NULL`。它有两个参数,第一个是文件名,第二个是打开模式,如`"r"`表示只读模式,`"w"`表示只写模式,`"a"`表示追加模式,`"b"`表示二进制模式,等等。
r:只读(必须存在,不存在打开失败!)
w:只写(存在则覆盖,不存在则创建)
a(append):(追加写,文件不存在相当于w)
r+ : 可读可写(不存在还是报错)
w+ : 可读可写(不存在创建)
a+ : 以追加方式打开可读写的文件,若文件不存在,则会建立该文件,如果文件存在,写入的数据会被加到文件尾后,即文件原先的内容会被保留。
示例代码:
FILE *fp = fopen("test.txt", "r"); //打开一个名为test.txt的文件,以只读模式
if (fp == NULL) {
printf("打开文件失败\n"); //如果文件不存在或无法打开,输出错误信息
}
2、`fclose`函数:int fclose(FILE *__stream)
用于关闭一个文件,释放文件指针占用的资源。它有一个参数,就是要关闭的文件指针。它返回一个整数,如果成功关闭,返回`0`,如果失败,返回`EOF`
示例代码:
int result = fclose(fp); //关闭文件
if (result == 0) {
printf("关闭文件成功\n"); //如果成功关闭,输出信息
} else {
printf("关闭文件失败\n"); //如果失败,输出错误信息
}
3、`fread`函数:size_t fread(void *__restrict__ __ptr, size_t __size, size_t __n, FILE *__restrict__ __stream)
用于从一个文件中读取数据,以二进制形式存储到一个缓冲区中。它有四个参数,第一个是缓冲区的地址,第二个是每个数据元素的大小,第三个是要读取的数据元素的个数,第四个是要读取的文件指针。它返回一个整数,表示实际读取到的数据元素的个数,如果到达文件末尾或发生错误,返回值可能小于第三个参数。
ptr : 读取数据的存放地址
size :一次读取的大小
n : 读取n次
返回值:实际读取的字数
示例代码:
int arr[10]; //定义一个整型数组,作为缓冲区
int n = fread(arr, sizeof(int), 10, fp); //从文件中读取10个整数,存入数组
if (n < 10) {
printf("读取文件结束或出错\n"); //如果读取到的个数小于10,输出信息
}
4、`fwrite`函数:size_t fwrite(const void *__restrict__ __ptr, size_t __size, size_t __n, FILE *__restrict__ __s)
用于向一个文件中写入数据,以二进制形式从一个缓冲区中读取数据。它有四个参数,第一个是缓冲区的地址,第二个是每个数据元素的大小,第三个是要写入的数据元素的个数,第四个是入的文件指针。它返回一个整数,表示实际写入的数据元素的个数,如果发生错误,返回值可能小于第三个参数。
示例代码:
int arr[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; //定义一个整型数组,作为缓冲区
int n = fwrite(arr, sizeof(int), 10, fp); //向文件中写入10个整数,从数组中读取
if (n < 10) {
printf("写入文件出错\n"); //如果写入的个数小于10,输出错误信息
}
5、 `fgetc`函数:int fgetc(FILE *__stream)
用于从一个文件中读取一个字符,返回该字符的ASCII码,如果到达文件末尾或发生错误,返回`EOF`。它有一个参数,就是要读取的文件指针。
示例代码:
char ch = fgetc(fp); //从文件中读取一个字符
if (ch == EOF) {
printf("读取文件结束或出错\n"); //如果读取到EOF,输出信息
} else {
printf("读取到的字符是%c\n", ch); //如果读取到正常的字符,输出信息
}
6、 `fputc`函数:int fputc(int __c, FILE *__stream)
用于向一个文件中写入一个字符,返回该字符的ASCII码,如果发生错误,返回`EOF`。它有两个参数,第一个是要写入的字符,第二个是要写入的文件指针。
示例代码:
char ch = 'A'; //定义一个字符
int result = fputc(ch, fp); //向文件中写入一个字符
if (result == EOF) {
printf("写入文件出错\n"); //如果写入失败,输出错误信息
} else {
printf("写入的字符是%c\n", result); //如果写入成功,输出信息
}
7、 `fgets`函数:char *fgets(char *__restrict__ __s, int __n, FILE *__restrict__ __stream)
用于从一个文件中读取一行字符串,存入一个字符数组中,遇到换行符或者结束符自动停止,自动在末尾添加`'\0'`。它有三个参数,第一个是字符数组的地址,第二个是要读取的最大字符数,第三个是要读取的文件指针。它返回一个指针,指向字符数组的首地址,如果到达文件末尾或发生错误,返回`NULL`。
示例代码:
char str[100]; //定义一个字符数组,作为缓冲区
char *p = fgets(str, 100, fp); //从文件中读取一行字符串,存入数组
if (p == NULL) {
printf("读取文件结束或出错\n"); //如果读取到NULL,输出信息
} else {
printf("读取到的字符串是%s\n", str); //如果读取到正常的字符串,输出信息
}
8、 `fputs`函数:int fputs(const char *__restrict__ __s, FILE *__restrict__ __stream)
用于向一个文件中写入一个字符串,不包括末尾的`'\0'`。它有两个参数,第一个是字符串的地址,第二个是要写入的文件指针。它返回一个整数,如果写入成功,返回一个非负值,如果发生错误,返回`EOF`。
示例代码:
char str[100] = "Hello, world!"; //定义一个字符串
int result = fputs(str, fp); //向文件中写入一个字符串
if (result == EOF) {
printf("写入文件出错\n"); //如果写入失败,输出错误信息
} else {
printf("写入的字符串是%s\n", str); //如果写入成功,输出信息
}
9、`fscanf`函数:int fscanf(FILE *__restrict__ __stream, const char *__restrict__ __format, ...)
用于从一个文件中按照指定的格式读取数据,类似于`scanf`函数,但多了一个参数,就是要读取的文件指针。它返回一个整数,表示成功读取的数据项的个数,如果到达文件末尾或发生错误,返回值可能小于指定的格式个数。
示例代码:
int x, y; //定义两个整数变量
int n = fscanf(fp, "%d%d", &x, &y); //从文件中按照格式读取两个整数,存入变量
if (n < 2) {
printf("读取文件结束或出错\n"); //如果读取到的个数小于2,输出信息
} else {
printf("读取到的两个整数是%d和%d\n", x, y); //如果读取到正常的整数,输出信息
}
10、`fprintf`函数:int fprintf(FILE *__restrict__ __stream, const char *__restrict__ __format, ...)
用于向一个文件中按照指定的格式写入数据,类似于`printf`函数,但多了一个参数,就是要写入的文件指针。它返回一个整数,表示成功写入的字符数,如果发生错误,返回一个负值。
示例代码:
int x = 10, y = 20; //定义两个整数变量
int n = fprintf(fp, "%d + %d = %d\n", x, y, x + y); //向文件中按照格式写入两个整数及其和
if (n < 0) {
printf("写入文件出错\n"); //如果写入失败,输出错误信息
} else {
printf("写入的字符数是%d\n", n); //如果写入成功,输出信息
}
11、`fseek`函数:int fseek(FILE *__stream, long __off, int __whence)
用来移动文件流的读写位置的函数,它可以让我们在文件中任意位置读写数据。
其中,`stream`是一个文件指针,表示要操作的文件流;`offset`是一个长整数,表示要移动的字节数,正数表示向后移动,负数表示向前移动;`whence`是一个整数,表示移动的起始位置,它有三个可能的取值:
- `SEEK_SET`,表示从文件开头开始移动,它的值为0;
- `SEEK_CUR`,表示从当前位置开始移动,它的值为1;
- `SEEK_END`,表示从文件末尾开始移动,它的值为2。
fseek函数的返回值是一个整数,如果执行成功,返回0;如果执行失败,返回非0值。
示例代码:
#include <stdio.h>
#include <stdlib.h>
int main()
{
FILE *fp; //定义一个文件指针
char buffer[100]; //定义一个缓冲区,用来存储文件内容
int len; //定义一个变量,用来记录文件长度
fp = fopen("test.txt", "r+"); //以读写模式打开一个文件
if (fp == NULL) //如果打开失败,退出程序
{
printf("打开文件失败\n");
exit(1);
}
fseek(fp, 0, SEEK_END); //将文件指针移动到文件末尾
len = ftell(fp); //获取文件长度
rewind(fp); //将文件指针重置到文件开头
fread(buffer, 1, len, fp); //将文件内容读取到缓冲区中
fseek(fp, 5, SEEK_SET); //将文件指针移动到文件开头的第5个字节处
fprintf(fp, "Hello, world!"); //在文件中插入一段字符串
fseek(fp, 0, SEEK_END); //将文件指针移动到文件末尾
fwrite(buffer + 5, 1, len - 5, fp); //将缓冲区中剩余的内容写入文件中
fclose(fp); //关闭文件
return 0;
}
12、`ftell`函数:long int ftell(FILE *stream)
其中,`stream`是一个文件指针,表示要操作的文件流。ftell函数的返回值是一个长整数,如果执行成功,返回文件指针的偏移量;如果执行失败,返回-1L。
用来获取文件流的当前位置的函数,它可以让我们知道文件指针相对于文件开头的偏移字节数。
示例代码:
#include <stdio.h>
int main()
{
FILE *fp; //定义一个文件指针
int len; //定义一个变量,用来记录文件长度
fp = fopen("test.txt", "w+"); //以读写模式打开一个文件
if (fp == NULL) //如果打开失败,退出程序
{
printf("打开文件失败\n");
return -1;
}
fprintf(fp, "Hello, world!"); //在文件中写入一段字符串
len = ftell(fp); //获取文件长度
fclose(fp); //关闭文件
printf("文件的总大小 = %d 字节\n", len); //输出文件长度
return 0;
}
13、`sprintf`函数:int sprintf(char *str, const char *format, ...)
格式化输出到字符串
14、`sscanf`函数:int sscanf(const char *str, const char *format, ...)
从字符串读取格式化输入。