2020.10.14 第16节课 文件操作
一、文件操作基础
基本流程 读写方式 类型 文件指针表示一个文件
**stdin: 标准输入 ---->键盘输入 fflush(stdin);
****stdout: 标准输出---->控台的窗口
自定义类型文件: 文件指针
*FILE fp;
1.打开文件
1.1 路径
1.2 读写方式
防御性编程 判空
2.关闭文件
把文件指针与文件的关联解除掉
#include <stdio.h>
stdin: 标准输入 ---->键盘输入 fflush(stdin);
stdout: 标准输出---->控台的窗口
自定义类型文件: 文件指针
FILE *fp;
1.打开文件
fopen(char *fileURL,char *mode);
1.1 路径
1.1.1 绝对路径 带盘符
1.1.2 相对路径
路径: 包含文件名字的后缀
1.2 读写方式
w: write 只写模式
r: read 只读
a: append 追加
------------------------------
b: binary 二进制
+: 可读可写
w+ r+ a+ wb+ rb+ ab+
-------------------------------
细致区别: w+ r+ a+
w: 清空原文件,文件不存在具有创建功能
a: 在原文件的后面
怎么写的就怎么读
zip
2.关闭文件
fclose(FILE* fp);
int main()
{
FILE* fp = fopen("2.doc", "w");
//一定要做判NULL
if (fp == NULL)
{
printf("文件打开失败!");
return 0;
}
FILE* fp2 = fopen("3.sb", "r");
if (fp2 == NULL)
{
printf("文件打开失败!");
return 0;
}
fclose(fp2);
fclose(fp);
return 0;
}
二、以字符或字符串的方式读写文件
字符和字符串的方式读写
1.fgetc+fputc();
2.fgets+fputs();
一行就是一个字符串
/*
字符和字符串的方式读写
fgetc+fputc();
fgets+fputs();
*/
#include <stdio.h>
int main()
{
char str[] = "ILoveyou,2020.11.14!";
//字符
FILE* write = fopen("1.txt", "w");
int i = 0;
while (str[i] != '\0')
{
//文件指针不许要自己移动,读写函数中有移动过程
fputc(str[i],write); //写文件
i++;
//write++;
}
fclose(write);
FILE* read = fopen("1.txt", "r");
int data = fgetc(read); //读文件,int 与char 可以通过ASCAII码转换
//EOF: 文件结束标记
while (data != EOF)
{
putchar(data);
data = fgetc(read);
}
fclose(read);
//字符串读写
FILE* writeStr = fopen("write.txt", "w");
//fputs(char *str,FILE *write); //字符串地址,文件指针
fputs(str, writeStr); //写文件 当前东西的数组名,写到那个地方去
fclose(writeStr);
//一行就是一个字符串
char readStr[10][1024] = { "" };
FILE* readFile = fopen("read.txt", "r");
// feof(readFile)
i = 0;
while (!feof(readFile))
{
//readStr[0]; readStr[0]
//readStr[1]; readStr[1]
//readStr[2]; reasStr[2]
fgets(readStr[i++], 1024, readFile); //读文件 读到哪 ,读哪个文件
}
for (int k = 0; k < 3; k++)
{
//puts(readStr[k]);
printf("%s", readStr[k]);
}
fclose(readFile);
return 0;
}
三、表格数据的读取
#include <stdio.h>
struct MM
{
char name[20];
int age;
int num;
};
/*
fprintf(FILE* fp,"格式",参数列表); printf
fscanf(FILE* fp,"格式",参数列表) ; scanf
规则 :怎么写怎么读即可
*/
int main()
{
struct MM myMM[3] = { "sr",18,1001,"baby",28,1002,"qq",38,1003 };
FILE* fp = fopen("mm.txt", "w");
for (int i = 0; i < 3; i++)
{
fprintf(fp, "%s\t%d\t%d\n", myMM[i].name, myMM[i].age, myMM[i].num);
}
fclose(fp);
FILE* read = fopen("mm.txt", "r");
//fscanf 返回值
struct MM tempMM;
while (fscanf(read, "%s\t%d\t%d\n", tempMM.name, &tempMM.age, &tempMM.num) != EOF)
{
printf("%s\t%d\t%d\n", tempMM.name, tempMM.age, tempMM.num);
}
//struct MM readMM[3];
弊端是你必须知道文件中有几条这样的数据
//for (int i = 0; i < 3; i++)
//{
// fscanf(read, "%s\t%d\t%d\n", readMM[i].name, &readMM[i].age, &readMM[i].num);
//}
fclose(read);
return 0;
}
四、字节流的形式读写文件
1.fread(void str,size_t size,int count,FILE file);
读到那 每次读多少 读几次 读谁
2.fwrite(void str,size_t size,int count,FILE file);
#include <stdio.h>
struct MM
{
char name[20];
int age;
int num;
};
/*
fread(void *str,size_t size,int count,FILE* file); 读到那 每次读多少 读几次 读谁
fwrite(void *str,size_t size,int count,FILE* file);
*/
int main()
{
struct MM myMM[3] = { "baby",13,1001,"qq",15,1002,"sr",18,1002 };
FILE* fp = fopen("1.txt", "wb");
//for (int i = 0; i < 3; i++)
//{
// fwrite(&myMM[i], sizeof(struct MM), 1, fp);
//}
fwrite(&myMM[0], sizeof(struct MM), 3, fp);
fclose(fp);
FILE* read = fopen("1.txt", "rb");
struct MM readMM[3];
fread(&readMM[0], sizeof(struct MM), 3, read);
for (int i = 0; i < 3; i++)
{
printf("%s\t%d\t%d\n", readMM[i].name, readMM[i].age, readMM[i].num);
}
fclose(read);
return 0;
}
五、文件指针移动
因为制表符的影响,也是占格式的 偏移不准确
<1>.格式化读写不能用文件指针移动操作!
<2>.字节流形式
rewind(FILE* fp); 把文件指针移动到文件开始的位置
fseek(FILE* fp,long count,int mode);
mode:
SEEK_CUR
SEEK_END
SEEK_SET
ftell(FILE *fp);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct MM
{
char name[20];
int age;
int num;
};
/* 因为制表符的影响,也是占格式的 偏移不准确
<1>.格式化读写不能用文件指针移动操作!
<2>.字节流形式
rewind(FILE* fp); 把文件指针移动到文件开始的位置
fseek(FILE* fp,long count,int mode);
mode:
SEEK_CUR
SEEK_END
SEEK_SET
ftell(FILE *fp);
*/
int main()
{
struct MM myMM[3] = { "baby",13,1001,"qq",15,1002,"sr",18,1002 };
FILE* fp = fopen("1.txt", "wb+");
fwrite(&myMM[0], sizeof(struct MM), 3, fp);
struct MM readMM[3];
rewind(fp);
fread(&readMM[0], sizeof(struct MM), 3, fp);
for (int i = 0; i < 3; i++)
{
printf("%s\t%d\t%d\n", readMM[i].name, readMM[i].age, readMM[i].num);
}
struct MM tempData;
//fseek(fp, sizeof(struct MM), SEEK_SET);
//fread(&tempData, sizeof(struct MM), 1, fp);
//printf("%s\t%d\t%d\n", tempData.name, tempData.age, tempData.num);
fseek(fp, sizeof(struct MM) * -2, SEEK_END);
fread(&tempData, sizeof(struct MM), 1, fp);
printf("%s\t%d\t%d\n", tempData.name, tempData.age, tempData.num);
fclose(fp);
FILE* readStr = fopen("read.txt", "r");
fseek(readStr, 0, SEEK_END);
//printf("%d\n", ftell(readStr));
int Length = ftell(readStr); //9
fseek(readStr, 0, SEEK_SET);
char* pStr = (char*)malloc(Length+1);
fgets(pStr, Length+1, readStr);
puts(pStr);
fclose(readStr);
return 0;
}
//memset(&readMM[0], 0, sizeof(struct MM) * 3); 读出来是垃圾值 给结构体内存初始化
//给这一段内存初始化为O
六、文件重定向
1.freopen(char str,int mode,FILE fp);
#include <stdio.h>
/*
freopen(char *str,int mode,FILE* fp);
*/
int main()
{
freopen("1.txt", "r+", stdin);
freopen("2.txt", "w+", stdout);
int a, b;
scanf("%d%d", &a, &b);
printf("%d", a+b);
return 0;
}
七、命令行参数
1.int argc: 命令行个数
2.char *argv[]: 记录命令
#include <stdio.h>
int main(int argc,char *argv[])
{
/*
int argc: 命令行个数
char *argv[]: 记录命令
*/
if (argc != 3)
{
printf("%s", argv[0]);
printf("指令使用错误!\n");
}
else
{
//copy: argv[0]
//1.txt :arv[1]
//2.txt :arv[2]
FILE* f1 = fopen(argv[1], "r");
FILE* f2 = fopen(argv[2], "w");
printf("覆盖 %s 吗? (Yes/No/All):", argv[2]);
int userKey = getchar();
if (userKey == 'y' || userKey == 'Y')
{
int data = fgetc(f1);
while (data != EOF)
{
fputc(data, f2);
}
printf("已复制 1 个文件。\n");
}
else
{
printf("已复制 0 个文件。\n");
}
fclose(f1);
fclose(f2);
}
return 0;
}