C语言程序17:文件操作
Merry Christmas
文件操作
一、文件基本操作
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
/*
文件基本操作:
1.文件基础
文本文件
二进制文件
----------------------
stdin: 标准输入 ----->键盘-->外设
stdout: 标准你输出---->程序-->控制台窗口
stderr: 标准出错
自定义类型文件--->文件指针
流:数据流--->从一个地方移动到另一个地方
2.基本操作流程
2.1 定义文件指针
FILE *fp=NULL;
2.2 打开文件
FILE* fopen(char *fileURL,char *mode);
fileURL:
相对路径-->相对于某一个文件,没有根目录
绝对路径-->可以根据目录找到相关文件
mode :
w: write 写的方式
r: read 读的方式
a: append 追加方式
组合性质
b:二进制+:可读可写
wb,rb,ab,
wb+,w+
a+,ab+
细致区别:
w+: 文件不存在,能够创建文件 文件存在会清空文件
r+: 不存在创建功能 ,不存在清空功能
a+: 文件不存在,能够创建文件,在原文件末尾接着写
强调一点:
<1>.读写方式一定要和操作一致,读写方式不对,读写操作一定错!
<2>.可以读写任何后缀结尾的!后缀是计算机文件的一种标识作用,重点在于改文件是如何读写的
2.3 读写文件
2.4 关闭文件
int fclose(FILE *fp);
文件打开失败,STREAM!=NULL
2.5 文件结束标记: EOF (-1) feof()
strcmp("str1","str2") >0
*/
//一般缓存文件如何做的
void readInfoToFile(char *fileName)
{
FILE *fp = fopen(fileName, "r");
if (fp == NULL)
{
fp = fopen(fileName, "w+");
}
fclose(fp);
}
int main()
{
FILE *fp = NULL;//1.定义文件指针
fp = fopen("write", "a+");
//防御性编程--->打开失败 返回NULL
if (fp == NULL)
{
printf("文件打开失败!\n");
system("pause");
return 0;
}
fclose(fp);//关闭文件指针
system("pause");
return 0;
}
二、以字符和字符串的方式读写
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
/*
1.读写函数包含文件指针移动,在读写文件不需要自己去移动文件指针
2.以字符的方式读写
file putchar
file getchar
读:int fgetc(FILE* fp);
写:int fputc(char ch,FILE* fp);
3.以字符串的方式读写
读: char* fgets(char *str,FILE* fp)
写: int fputs(char *str,int count,FILE* fp);
//这个叫按行读写
*/
int main()
{
//字符的方式去写操作
char data[] = { "ILoveyou!" };
FILE *fp = fopen("write.txt", "w");
//string.h: strlen char * 等效C++cstring
//string:C++ 类
//字符写
//for (int i = 0; i <= strlen(data); i++)
//{
//fputc(data[i], stdout); //putchar();
//fputc(data[i], fp);
//}
//字符串写
fputs(data, fp);
printf("\n");
fclose(fp);
//字符读写的弊端:大小问题
//字符读的方式
FILE *read = fopen("gets.txt", "r");
char readStr[2][1024] = {""};
//以字符的方式读
//int i = 0;
//while (!feof(read))
//{
//readStr[i++] = fgetc(read);
//}
//以字符串的去读
//多行文件读写
int count = 0;
while (!feof(read))
{
fgets(readStr[count], 1024, read);
printf("%s", readStr[count]);
count++;
}
printf("\n");
fclose(read);
system("pause");
return 0;
}
三、格式化读写(结构体方式读写文件)
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
struct MM
{
char name[20];
int age;
int num;
double score;
};
/*
//写操作
fprintf(FILE* file,char *str,....);
//读操作
fscanf(FILE* file,char *str,....);
除了指定一个file作为目的地,其他的和printf函数以及scanf函数一样的用法
fprintf(stdout, "%d\n%s\n", 1, "name1");
int num=0;
char name[20] = "";
fscanf(stdin, "%d%s", &num, name);
printf("%d\t%s\n", num, name);
//!格式读写不适用与文件指针移动函数
*/
int main()
{
/* 文件写操作
struct MM data[4] =
{
"name1", 18, 1001, 12.1,
"name2", 65, 1002, 13.1,
"name3", 25, 1003, 93.1,
"name4", 98, 1005, 19.0
};
FILE *fp = fopen("MM.txt", "w");
for (int i = 0; i < 4; i++)
{
//宛如学习printf函数
fprintf(fp, "%s\t%d\t%d\t%.1lf\n", data[i].name, data[i].age, data[i].num, data[i].score);
}
fclose(fp);
*/
FILE *read = fopen("MM.txt", "r");
struct MM readData[4];
int count = 0;
int num;
//允许存在格式控制字符,不能存在精度调整
while (fscanf(read, "%s\t%d\t%d\t%lf\n", readData[count].name,
&readData[count].age, &readData[count].num, &readData[count].score) != EOF)
{
count++;
}
for (int i = 0; i < 4; i++)
{
printf("%s\t%d\t%d\t%.1lf\n", readData[i].name, readData[i].age, readData[i].num, readData[i].score);
}
fclose(read);
system("pause");
return 0;
}
四、字符流的读写方式
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/*
fread(void *buf,size_t size,size_t,FILE *fp);
fwrite(void *buf,size_t size,size_t,FILE *fp);
写到文件中是乱码,是很正常的--->要注意的是只能能够读出来即可
*/
struct MM
{
char name[20];
int age;
int num;
double score;
};
int main()
{
//文件写操作
struct MM data[4] =
{
"name1", 18, 1001, 12.1,
"name2", 65, 1002, 13.1,
"name3", 25, 1003, 93.1,
"name4", 98, 1005, 19.0
};
FILE *fp = fopen("MM.txt", "wb");
//for (int i = 0; i < 4; i++)
//{
//fwrite(&data[i], sizeof(struct MM), 1, fp);
//}
//等效上面的循环
fwrite(data, sizeof(struct MM), 4, fp);
fclose(fp);
FILE *read = fopen("MM.txt", "rb");
struct MM readData[4];
//int count = 0;
fread(readData, sizeof(struct MM), 4, read);
for (int i = 0; i < 4; i++)
{
printf("%s\t%d\t%d\t%.1lf\n", readData[i].name, readData[i].age, readData[i].num, readData[i].score);
}
fclose(read);
system("pause");
return 0;
}
五、文件夹指针移动
#define _CRT_SECURE_NO_WARNINGS
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
/*
操作文件转换:
1.int ftell(FILE *fp);文件移动多少位置--->fgets做动态内存申请
2.rewind(FILE *fp);文件指针移动开始位置
3.fseek(FILE* fp,long count,int mode);
count:移动多少个位置
正数:往前
负数:往后
mode:参照点
SEEK_SET 开始的位置
SEEK_END 结束的位置
SEEK_CUR 当前的位置
*/
struct MM
{
char name[20];
int age;
int num;
double score;
};
int main()
{
//文件写操作
struct MM data[4] =
{
"name1", 18, 1001, 12.1,
"name2", 65, 1002, 13.1,
"name3", 25, 1003, 93.1,
"name4", 98, 1005, 19.0
};
FILE *fp = fopen("MM.txt", "wb+");
fwrite(data, sizeof(struct MM), 4, fp);//文件指针到达文件末尾
printf("sizeof(MM):%d\n", sizeof(struct MM));
printf("size=:%d\n", ftell(fp));
struct MM readData[4];
//int count = 0;
rewind(fp);
fread(readData, sizeof(struct MM), 4, fp);
for (int i = 0; i < 4; i++)
{
printf("%s\t%d\t%d\t%.1lf\n", readData[i].name, readData[i].age, readData[i].num, readData[i].score);
}
//通过文件指针移动读取最后一个人的信息:
//当前位置,文件指针在文件末尾
printf("文件指针移动读取最后一个人的信息!:\n");
long size = sizeof(struct MM); //总共需要移动字节数
fseek(fp, -2 * size, SEEK_END); //往后移动,要写负数
struct MM tempData;
fread(&tempData, sizeof(struct MM), 1, fp);
printf("%s\t%d\t%d\t%.1lf\n", tempData.name, tempData.age, tempData.num, tempData.score);
fclose(fp);
system("pause");
return 0;
}
六、文件重定向
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
/*
文件重定向:把程序所有输入和输出定向文件
当前程序是没有任何效果。
freopen(char *fileName,char *mode,FILE *file)
*/
int sum(int a, int b)
{
return a + b;
}
int main()
{
freopen("2.txt", "r", stdin);
int a = 0, b = 0;
scanf("%d%d", &a, &b);//从文件当中获取数据
freopen("1.txt", "w", stdout);
printf("sum=%d\n", sum(a, b));
return 0;
}
七、主函数参数
#include <stdio.h>
#include <stdlib.h>
int main(int argc,char*argv[])
{
//用到主函数参数的程序:一般称为命令行程序
//编译运行不了--->只有控制台输入指令
//argc: 指令个数
//copy 1.txt 2.txt argc=3
//argv[0]: exe的目录
//argv[1]: 1.txt
//argv[2]: 2.txt
if (argc != 3)
{
printf("USE 指令 file1 file2\n");
}
else
{
printf("argv[0]:%s\n", argv[0]);
}
system("pause");
return 0;
}
八、mycopy
#define _CRT_SECURE_NO_WARNINGS
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char*argv[])
{
//用到主函数参数的程序:一般称为命令行程序
//编译运行不了--->只有控制台输入指令
//argc: 指令个数
//copy 1.txt 2.txt argc=3
//argv[0]: exe的目录
//argv[1]: 1.txt
//argv[2]: 2.txt
if (argc != 3)
{
printf("USE 指令 file1 file2\n");
}
else
{
FILE *file1 = fopen(argv[1], "r");
FILE *file2 = fopen(argv[2], "w");
if (file1 == NULL || file2 == NULL)
{
printf("系统找不到指定的文件。\n");
return 0;
}
printf("覆盖 %s 吗? (Yes/No/All):",argv[2]);
char userKey = getchar();
if (userKey == 'y' || userKey == 'Y')
{
int key = fgetc(file1);
while (key != EOF)
{
fputc(key, file2);
key = fgetc(file1);
}
printf("已复制 1 个文件。\n\n");
}
else
{
printf("已复制 0 个文件。\n\n");
}
fclose(file1);
fclose(file2);
}
return 0;
}
我知道你在看哟
新浪微博:@秀米XIUMI