fprintf
fprintf 是将源文件内的数据打印到文件中去
int fprintf(FILE *stream, const char *format, ...)
返回值
如果成功,则返回写入的字符总数,否则返回一个负数
fscanf
fscanf是将文件的内容读取,然后给源文件的变量
int fscanf(FILE *stream, const char *format, ...)
返回值
如果成功,该函数返回成功匹配和赋值的个数。如果到达文件末尾或发生读错误,则返回 EOF
rewind
rewind是将光标移到文件开始的地方
我们对文件写操作的时候,往往光标就移到了文件末尾,如果不用这个可能再次读就读不到
void rewind(FILE *stream)
ftell
ftell是返回从光标到文件开头之间的字节数
long int ftell(FILE *stream)
返回值
该函数返回位置标识符的当前值。如果发生错误,则返回 -1L,全局变量 errno 被设置为一个正值
fseek
是将光标移动到想要的位置
这样我们就可以对文件进行修改了,找到该位置,用fputs函数就可以将原来位置的内容进行替换,但我觉得这样是不保险的,因为字长要一样,要不然可能会出现错误的数据,以后应该会学到更好的方法
int fseek(FILE *stream, long int offset, int whence)
返回值
如果成功,则该函数返回零,否则返回非零值
这里我定义了一个结构体,将结构体的内容通过fprintf打印到文件中,再将文件中的内容读取到定义的另一个结构体数组中,在终端打印出来
用ftell看文件有多少个字节的内容
然后用fseek将第一条信息的名字做修改
#include<stdio.h>
typedef struct
{
int id;
char name[20];
float score;
char sex;
}MSG;
int main()
{
MSG msg[4] = {{1001, "陈奕迅", 96.5, 'm'},
{1002, "林俊杰", 97.7, 'm'},
{1003, "蔡依林", 98.5, 'f'},
{1004, "田馥甄", 87.5, 'f'}};
// int id = 1001;
// char name[20] = "周杰伦";
// float score = 92.5;
// char sex = 'm';
FILE *fp = fopen("./1.txt", "r+");
if(fp == NULL)
{
perror("Error");
}
MSG r_msg[4];
for(int i = 0; i < 4; i++)
fprintf(fp, "%d %s %.1f %c\n", msg[i].id, msg[i].name, msg[i].score, msg[i].sex);
rewind(fp);
for(int i = 0; i < 4; i++)
fscanf(fp, "%d %s %f %c", &r_msg[i].id, r_msg[i].name, &r_msg[i].score, &r_msg[i].sex);
for(int i = 0; i < 4; i++)
printf("%d, %s, %.1f, %c\n", r_msg[i].id, r_msg[i].name, r_msg[i].score, r_msg[i].sex);
long ret = ftell(fp);//返回从光标位置到文件起始位置的字节数
printf("%ld\n", ret);
fseek(fp, 5, SEEK_SET);
fputs("周杰伦", fp);
return 0;
}
重定向
重定向,通俗的来讲就是通过运用freopen函数将本该给终端打印的内容,打进了文件中,像这样做,就用stdout标准输出来控制;也可以用freopen函数将文件的内容,copy到数组中然后在终端输出
freopen
FILE *freopen(const char *filename, const char *mode, FILE *stream)
FILE *fp = freopen("stdout.txt", "w", stdout);
中间的mode和之前打开文件的mode一样
"r" | 打开一个用于读取的文件。该文件必须存在。 |
"w" | 创建一个用于写入的空文件。如果文件名称与已存在的文件相同,则会删除已有文件的内容,文件被视为一个新的空文件。 |
"a" | 追加到一个文件。写操作向文件末尾追加数据。如果文件不存在,则创建文件。 |
"r+" | 打开一个用于更新的文件,可读取也可写入。该文件必须存在。 |
"w+" | 创建一个用于读写的空文件。 |
"a+" | 打开一个用于读取和追加的文件。 |
stream -- 这是指向 FILE 对象的指针,该 FILE 对象标识了要被重新打开的流,stdout、stdin、stderror
也可以在中途关掉这个被打开的流
例如你在重定向的时候用的是stdout,可以在代码中加入fclose(stdout),这样你做的输出操作就和文件没有什么交互了,也不可以正常的在终端输出,文件也不会保存输出内容,这样关的不太彻底,用下面的方法就可以彻底把freopen关掉了
freopen("CON", "w", stdout);
用了这个可以正常在屏幕上打印内容了
#include<stdio.h>
int main()
{
FILE *fp = freopen("stdout.txt", "w", stdout);
if(fp == NULL)
{
perror("Error");
}
puts("a");
puts("b");
fclose(stdout);
puts("c");
puts("d");
freopen("CON", "w", stdout);
puts("1");
puts("2");
fclose(fp);
return 0;
}
这样文件中就有了a b 1 2这四个数据,而c d不会保存到文件中;
下来可以使用freopen将文件内容读取,然后保存到数组中,然后再终端输出这个数组
#include<stdio.h>
int main()
{
FILE *fp = freopen("stdin.txt", "r", stdin);
if(fp == NULL)
perror("Error");
char name[30];
fgets(name, 100, fp);
puts(name);
return 0;
}
记得,用写到文件的时候用w,用读文件内容的时候用r
总结:
这两天讲的文件,内容不难,但是那些读取文件模式了解的有点少,他们之间的联系和区别都有什么,这些可能有些薄弱,需要再加强一下