1. 文件
C语言中,在进行数据处理时,如果只通过变量进行存储数据,那么在程序结束时,我们对变量存储的数据也就一同释放掉了,如果下次在启动该程序,就要重新录入数据,就要在无意义上的事情浪费巨量的时间。所以引入了文件的概念,将数据存储到文件上,每次对文件内的数据进行读取与存储,就大大方便了使用者。
2. c语言中如何使用文件
1). 文件指针的使用
C语言中的文件操作都是通过一个指向文件的指针进行操作。FILE* fp
这是定义了一个指向某个文件的指针,对该指针进行某操作就是对其指向的文件进行操作。
接下来通过一个程序来进行文件才做的简单示例。
#include <stdio.h>
int main()
{
FILE* fp;
// 将文件以写的方式打开
// 文件打开成功返回地址,打开失败则返回NULL
fp = fopen(“filename.XXX”, “w”);
// 如果文件打开失败,则退出该程序
if(fp == NULL)
{
return -1;
}
// 对文件进行操作
// ………
// ***关闭文件***
fclose(fp);
return 0;
}
2). 文件打开方式图示
3). 文件读取结束的判定
EOF为文件读取结束时返回的标记,具体是文件读取失败结束,还是遇到文件尾结束需要具体判断。
- 文本文件读取是否结束,判断返回值是否为
EOF
,或者是NULL
。
fgetc()
判断是否为EOF
fgets()
判断是否为NULL
- 二进制文件读取结束的判断,判断返回值是否为小于实际要读的个数
fread()
判断返回值是否小于实际要读个数
示例:
文本文件读取失败
#include <stdio.h>
int main()
{
int c;
// 以文本形式打开文件
FILE *fp = fopen("test.txt", "r");
if(!fp)
{
perror("file open failed");
return -1;
}
// 通过fgetc 函数读取文件,在读取失败时会返回EOF
while((c = fgetc(fp) != EOF)
{
putchar(c);
}
// 判断文件是以什么原因结束读取
if(ferror(fp)) // 文件读取失败
puts("I/O error when reading");
else if(feof(fp)) // 遇到文件尾
puts("end of file");
fclose(fp);
return 0;
}
二进制文件读取失败
#include <stdio.h>
#define SIZE 5
int main()
{
FILE* fp = fopen("test", "rb");
double b[5];
size_t ret_code = fread(b, siezof * b, SIZE, fp); // 从文件中读取数据
if(ret_code == SIZE) // 文件读取成功
{
puts("Array read successful");
}
else
{
// 判断文件是以什么原因结束读取
if(ferror(fp)) // 文件读取失败
puts("I/O error when reading");
else if(feof(fp)) // 遇到文件尾
puts("end of file");
}
fclose(fp);
return 0;
}
4). 文件缓冲区
我们向文件中写入数据时,系统并不会直接将写入数据存入文件中,因为CPU运算速度与存储设备写入速度差别很大,所以为了匹配二者速度,会将待写入数据存入文件缓冲区,待文件缓冲区满后一并写入文件。也可主动刷新缓冲区,将文件写入存储设备,通过fflush(fp)
;
3. 通过文件操作实现各类函数加密解密
代码
#include <stdio.h>
#include <stdlib.h>
#include "des.h"
#define SIZE 1024*4
void menu()
{
printf("=============================\n");
printf("1.加密文件\n");
printf("2.解密文件\n");
printf("3.清屏\n");
printf("4.退出\n");
printf("=============================\n");
}
// 加密文件
void EncFile()
{
// 以4k大小读文件,srcBuf
// rBuf 加密 -> dstBuf
// dstBuf -> 写文件
FILE* rFd = NULL;
FILE* wFd = NULL;
char rPath[512] = { 0 }; // 源文件路径(需要加密文件路径)
char wPath[512] = { 0 }; // 目标路径(保存加密后的文件)
unsigned char srcBuf[SIZE] = { 0 }; // 4k 所读文件的存储
int rLen = 0; // 所读文件长度
unsigned char dstBuf[SIZE] = { 0 }; // 4k 加密后要向文件中写的存储
int wLen = 0; // 加密后要写文件的长度
int ret = 0; // 接收函数返回值
printf("请输入需要加密的文件名:");
scanf("%s", rPath);
printf("请输入加密后的文件名:");
scanf("%s", wPath);
// 读方式打开需要加密的文件 rPath
rFd = fopen(rPath, "rb+");
if (rFd == NULL)
{
perror("EncFile fopen rPath");
return;
}
// 写方式打开加密后的文件 wPath
wFd = fopen(wPath, "wb+");
if (wFd == NULL)
{
perror("EncFile fopen wPath");
goto End;
return;
}
// 循环读取文件
while (1)
{
rLen = fread(srcBuf, 1, SIZE, rFd);
if (rLen < SIZE) // 当文件小于4k时跳出循环,执行下方 < 4k 文件加密
{
break;
}
// srcBuf 加密 -> dstBuf
ret = DesEnc_raw(srcBuf, rLen, dstBuf, &wLen);
if (ret != 0)
{
printf("DesDec_raw 加密=4k数据失败\n");
goto End;
return;
}
// 写加密后的文件
ret = fwrite(dstBuf, 1, wLen, wFd);
if (ret != wLen)
{
printf("写加密后的文件=4k数据失败\n");
goto End;
return;
}
}
// 小于4k大小读文件,srcBuf
// rBuf 加密 -> dstBuf
// dstBuf -> 写文件
// srcBuf 加密 -> dstBuf
ret = DesEnc(srcBuf, rLen, dstBuf, &wLen);
if (ret != 0)
{
printf("DesDec 加密 < 4k数据失败\n");
goto End;
return;
}
// 写加密后的文件
ret = fwrite(dstBuf, 1, wLen, wFd);
if (ret != wLen)
{
printf("写加密后的文件 < 4k数据失败\n");
goto End;
return;
}
End:
if (rFd != NULL)
{
fclose(rFd);
rFd = NULL;
}
if (wFd != NULL)
{
fclose(wFd);
wFd = NULL;
}
}
// 解密文件 (与加密文件相反)
void DecFile()
{
// 以4k大小读文件,srcBuf
// rBuf 解密 -> dstBuf
// dstBuf -> 写文件
FILE* rFd = NULL;
FILE* wFd = NULL;
char rPath[512] = { 0 }; // 源文件路径(需要解密文件路径)
char wPath[512] = { 0 }; // 目标路径(保存解密后的文件)
unsigned char srcBuf[SIZE] = { 0 }; // 4k 所读文件的存储
int rLen = 0; // 所读文件长度
unsigned char dstBuf[SIZE] = { 0 }; // 4k 解密后要向文件中写的存储
int wLen = 0; // 解密后要写文件的长度
int ret = 0; // 接收函数返回值
printf("请输入需要解密的文件名:");
scanf("%s", rPath);
printf("请输入解密后的文件名:");
scanf("%s", wPath);
// 读方式打开需要解密的文件 rPath
rFd = fopen(rPath, "rb+");
if (rFd == NULL)
{
perror("EncFile fopen rPath");
return;
}
// 写方式打开解密后的文件 wPath
wFd = fopen(wPath, "wb+");
if (wFd == NULL)
{
perror("EncFile fopen wPath");
goto End;
return;
}
// 循环读取文件
while (1)
{
rLen = fread(srcBuf, 1, SIZE, rFd);
if (rLen < SIZE) // 当文件小于4k时跳出循环,执行下方 < 4k 文件解密
{
break;
}
// srcBuf 解密 -> dstBuf
ret = DesDec_raw(srcBuf, rLen, dstBuf, &wLen);
if (ret != 0)
{
printf("DesDec_raw 解密=4k数据失败\n");
goto End;
return;
}
// 写解密后的文件
ret = fwrite(dstBuf, 1, wLen, wFd);
if (ret != wLen)
{
printf("写解密后的文件=4k数据失败\n");
goto End;
return;
}
}
// 小于4k大小读文件,srcBuf
// rBuf 解密 -> dstBuf
// dstBuf -> 写文件
// srcBuf 解密 -> dstBuf
ret = DesDec(srcBuf, rLen, dstBuf, &wLen);
if (ret != 0)
{
printf("DesDec 解密 < 4k数据失败\n");
goto End;
return;
}
// 写解密后的文件
ret = fwrite(dstBuf, 1, wLen, wFd);
if (ret != wLen)
{
printf("写解密后的文件 < 4k数据失败\n");
goto End;
return;
}
End:
if (rFd != NULL)
{
fclose(rFd);
rFd = NULL;
}
if (wFd != NULL)
{
fclose(wFd);
wFd = NULL;
}
}
int main()
{
int cmd;
while (1)
{
menu();
printf("cmd:");
scanf("%d", &cmd);
switch (cmd)
{
case 1: EncFile(); break;
case 2: DecFile(); break;
case 3: system("cls"); break;
default: exit(0); break;
}
}
return 0;
}