目录:
一 : FILE结构体
二 :获取文件 fopen()、fclose() :
三 :获取一行fgets():
四 :写入一行fputs():
五 :设置位置fseek()、 获取当前位置ftell()
六 :小结
七 :作业
一、FILE 结构体:
struct _iobuf {
char *_ptr;
int _cnt;
char *_base;
int _flag;
int _file;
int _charbuf;
int _bufsiz;
char *_tmpfname;
};
tpyedef struct _iobuf FILE;
正常情况下,我们使用的都是FILE结构体的指针
二、获取文件 fopen()、fclose() :
功能:打开 关闭文件
1 fopen():
原型:
FILE * fopen(const char *path, const char *mode);
第一个参数: path 读取文件路径
第二个参数: mode 文件使用的模式
常见模式(mode):
read 读
write 写
addit 附加
返回值 是一个FILE结构体的地址
2 fclose() :
fclose() 则是将文件结构体指针传入,然后释放改文件,情况类似free()函数
三、fgets():
读取相应的文件,类似gets() 函数一次读取一行
原型:
char *fgets(char *buf, int bufsize, FILE *stream);
第一个参数: buf 缓冲缓存
第二个参数: bufsize 知名前面的大小
第三个参数: stream file结构体,在这里对其操作
#include<stdio.h>
int main() {
FILE *fp;
char buf[20];
fp = fopen("E:\\1.txt", "r");
fgets(buf, 20, fp);
printf(buf);
return 0;
}
PS: 关于路径写法问题 windows的路径是\\,ubuntu是/
(https://blog.youkuaiyun.com/zjc910997316/article/details/84405031)
#include<stdio.h>
#include<windows.h>
int main() {
FILE *fp; // FILE结构体
char buf[20];
// 打开文件
fp = fopen("H:\\(VS)2012\\Archer_project\\Test1\\1.txt", "r"); // r 只读模式
if (fp == NULL) {
printf("打开文件失败");
}
// 获取文件
fgets(buf, 20, fp);
printf("%s", buf);
// 关闭文件
fclose(fp);
Sleep(10000);
}
如果1.txt 文件里面是
hello world
hi alan
只能获取一行
如下即可获取第二行:
#include<stdio.h>
#include<windows.h>
int main() {
FILE *fp; // FILE结构体
char buf[20];
// 打开文件
fp = fopen("H:\\(VS)2012\\Archer_project\\Test1\\1.txt", "r"); // r 只读模式
if (fp == NULL) {
printf("打开文件失败");
}
// 获取文件
fgets(buf, 20, fp);
printf("%s", buf);
// 获取文件 第二行
fgets(buf, 20, fp);
printf("%s", buf);
// 关闭文件
fclose(fp);
Sleep(10000);
}
同理,使用多次,可以获取多行
循环读取:
下面是循环读取,直到没有
#include<stdio.h>
#include<windows.h>
int main() {
FILE *fp; // FILE结构体
char buf[20];
// 打开文件
fp = fopen("H:\\(VS)2012\\Archer_project\\Test1\\1.txt", "r"); // r 只读模式
if (fp == NULL) {
printf("打开文件失败");
}
// 获取文件
while(fgets(buf, 20, fp)) { // 如果读到结尾会返回一个空,这样就不会继续再读取
printf("%s", buf);
}
// 关闭文件
fclose(fp);
Sleep(10000);
}
宏定义:
定义一个宏定义,随时来改变buf size大小
#include<stdio.h>
#include<windows.h>
#define BUFSIZE 20 // 宏定义
int main() {
FILE *fp;
char buf[ BUFSIZE ]; // 宏定义
// 打开文件
fp = fopen("H:\\(VS)2012\\Archer_project\\Test1\\1.txt", "r");
if (fp == NULL) {
printf("打开文件失败");
}
// 获取文件
while(fgets(buf, BUFSIZE , fp)) { // 宏定义
printf("%s", buf);
}
// 关闭文件
fclose(fp);
Sleep(10000);
四、fputs():
写入相应的文件,类似puts()函数,一次写一行
原型:
int fputs(char *str, FILE *fp);
#include<stdio.h>
int main() {
FILE *fp;
char buf[20] = "hello world";
fp = fopen("E:\\1.txt", "w");
fputs(buf, fp);
return 0;
}
一次写入一行
把 buf[BUFSIZE] 里面的内容写入到 1.txt 文件里面:
#include<stdio.h>
#include<windows.h>
#define BUFSIZE 52
int main() {
FILE * f;
char buf[BUFSIZE] = "This is fputs function! \nhello fputs!";
f = fopen("C:\\1.txt", "w");
if (NULL ==f) { // ==是比较, =是赋值。NULL == f这样写可以避免写错成NULL = f,因为NULL常值不会被赋值
printf("write file failed!");
}
fputs(buf, f);
fclose(f);
}
成功写入
五、fseek()、 ftell()
fseek() 设置文件位置
ftell() 获取当前位置
int fseek(FILE *stream, long offset, int fromwhere);
第一个参数 是要操作的文件流指针(即文件结构体)
第二个参数 偏移量
第三个参数 偏移的相对的位置 , 针对什么地方的偏移
常见的位置有:
SEEK_SET: 文件开头
SEEK_CUR: 当前位置
SEEK_END: 文件结尾
ftell()的原型:
long ftell(FILE *stream);
通过文件结构体指针获取当前指向的位置
fgets():
#include<stdio.h>
#include<windows.h>
#define BUFSIZE 100
int main() {
FILE *fp; // FILE结构体
char buf[BUFSIZE];
// 打开文件
fp = fopen("C:\\1.txt", "r"); // r 只读模式
if (fp == NULL) {
printf("打开文件失败");
}
// 获取文件
fgets(buf, BUFSIZE, fp);
printf("%s\n", buf);
fseek(fp, 0, SEEK_SET); // 前面虽然读过第一行了,这个函数从新置到起始位置,把第一行又读一遍
fgets(buf, BUFSIZE, fp);
printf("%s\n", buf);
// 关闭文件
fclose(fp);
Sleep(10000);
}
注释掉fseek()
#include<stdio.h>
#include<windows.h>
#define BUFSIZE 100
int main() {
FILE *fp; // FILE结构体
char buf[BUFSIZE];
// 打开文件
fp = fopen("C:\\1.txt", "r"); // r 只读模式
if (fp == NULL) {
printf("打开文件失败");
}
// 获取文件
fgets(buf, BUFSIZE, fp);
printf("%s\n", buf);
//fseek(fp, 0, SEEK_SET);
fgets(buf, BUFSIZE, fp);
printf("%s\n", buf);
// 关闭文件
fclose(fp);
Sleep(10000);
}
如果设置为5偏移量,从第五个开始读
#include<stdio.h>
#include<windows.h>
#define BUFSIZE 100
int main() {
FILE *fp; // FILE结构体
char buf[BUFSIZE];
// 打开文件
fp = fopen("C:\\1.txt", "r"); // r 只读模式
if (fp == NULL) {
printf("打开文件失败");
}
// 获取文件
fgets(buf, BUFSIZE, fp);
printf("%s\n", buf);
fseek(fp, 5, SEEK_SET);
fgets(buf, BUFSIZE, fp);
printf("%s\n", buf);
// 关闭文件
fclose(fp);
Sleep(10000);
}
SEEK_END
相对于结尾来偏移
#include<stdio.h>
#include<windows.h>
#define BUFSIZE 100
int main() {
FILE *fp; // FILE结构体
char buf[BUFSIZE];
// 打开文件
fp = fopen("C:\\1.txt", "r"); // r 只读模式
if (fp == NULL) {
printf("打开文件失败");
}
// 获取文件
fgets(buf, BUFSIZE, fp);
printf("%s\n", buf);
fseek(fp, -5, SEEK_END); // 相对于结尾来偏移
fgets(buf, BUFSIZE, fp);
printf("%s\n", buf);
// 关闭文件
fclose(fp);
Sleep(10000);
}
输出文件最后五个字符
六、小结
(这里是不是写反了? 答案是:没)
一。基本操作
1.FILE 文件结构体
2.fopen()文件的打开
3.fclose() 文件的关闭
fopen()文件的打开:
r 读
r+ 读的同时可以写,
w+ 写的同时可以读,
r+ w+区别:
r+ 去读取位置去读文件,如果没有文件一定读不到。
w+ 写的同时去读,如果读不到,就会自己去创建这个文件
二。文件读写
1.fget()文件读取 读文件,读完一行,指针会下移动,如果buf没读完一行,此次在读取就会从没读完的位置继续读
2.fputs()文件写入
三。文件位置操作
1.ftell() 获取当前文件操作的位置
2.fseek() 设置文件操作的位置
七、作业
r模式 需要有事先准备好的文件,所以1.txt, 2.txt需要提前写好
w模式 会自动创建文件,因此3.txt, 4.txt, 5.txt都不需要提前创建
1.txt, 2.txt的文件分别是
提前准备1.txt:
i
ii
iii
要注意多回车一行,
不然后面do{}while(now!=flag)将会无法成立,
可以改成do{}while( flag > now);来实现
do { // 写入4.txt
fgets(buf, 100, fp3);
fputs(buf, fp_cut1);
printf("%s", buf);
now = ftell(fp3);
//printf("flag is %long", flag);
//printf("now is %long", now);
//Sleep(10000);
//i++;
} while( flag > now);
提前准备2.txt:
o
oo
ooo
这里不需要回车,
但是前面留空行,这样看着更方便~
完整代码:
#include<stdio.h>
#include<windows.h>
int main() {
FILE *fp1, *fp2, *fp3, *fp_w; // FILE结构体
FILE *fp_cut1, *fp_cut2;
char buf[100];
long flag, now; // flag用于标记位置,now记录fp3当前位置
// 打开文件
fp1 = fopen("C:\\1.txt", "r"); // r 只读模式
fp2 = fopen("C:\\2.txt", "r"); // r 只读模式
fp_w = fopen("C:\\3.txt", "w");
// 第一部分fp1: 读取1.txt写入3.txt
if (fp1 == NULL) {
printf("1.txt打开文件失败");
}
printf("下面是1.txt内容:\n");
while ( fgets(buf, 100, fp1) ) { // 直到读不到停止
printf("%s", buf);
fputs(buf, fp_w); // 写入
}
//记录在3.txt中的位置
flag = ftell(fp_w);
printf("\n\n标记位置为:%lon\n", flag);
// 第二部分fp2: 读取2.txt写入3.txt
if (fp2 == NULL) {
printf("2.txt打开文件失败");
}
printf("\n下面是2.txt内容:\n");
while ( fgets(buf, 100, fp2) ) { // 直到读不到停止
printf("%s", buf);
fputs(buf, fp_w); // 写入
}
fclose(fp_w); // fp_w: 通过关掉fp_w关掉文件3.txt,才能在下面fp3再次打开
//Sleep(10000);
// 第三部分fp3: 读取3.txt展示出来
fp3 = fopen("C:\\3.txt", "r"); // r 只读模式
if (fp3 == NULL) {
printf("3.txt打开文件失败");
}
printf("\n\n下面是3.txt内容:\n");
while(fgets(buf, 100, fp3)) { // 如果读到结尾会返回一个空,这样就不会继续再读取
printf("%s", buf);
}
// 第四部分fp_cut1: 把3.txt中flag标记前面的内容写入4.txt
printf("\n\n下面是4.txt内容:\n");
fseek(fp3, 0, SEEK_SET); // 3.txt中标记开头
fp_cut1 = fopen("C:\\4.txt", "w");
do { // 写入4.txt
fgets(buf, 100, fp3);
fputs(buf, fp_cut1);
printf("%s", buf);
now = ftell(fp3);
//printf("flag is %long", flag);
//printf("now is %long", now);
//Sleep(10000);
//i++;
} while( flag != now);
printf("\nflag is %long", flag);
printf("\nnow is %long", now);
// 第五部分fp_cut2: 把3.txt中flag标记后面的内容写入5.txt
printf("\n\n下面是5.txt内容:\n");
fseek(fp3, flag, SEEK_SET); // 3,txt中标记开头
fp_cut2 = fopen("C:\\5.txt", "w");
while(fgets(buf, 100, fp3)) {
fputs(buf, fp_cut2); // 写入5.txt
printf("%s", buf);
}
// 关闭文件
fclose(fp1);
fclose(fp2);
fclose(fp3);
fclose(fp_cut1);
fclose(fp_cut2);
Sleep(10000);
}
’结果: