二进制读写才是本质
二进制的读写对文件标记不敏感。
eg: 对图片进行加密与解密:
用命令的形式去执行:
//xx.exe -c src dest 加密
//xx.exe -d src dest 解密
他的参数就是argv[0-3]------使用Qt
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
void encode(char *buf,int n) {
for(int i = 0;i < n;i++) {
buf[i]++;
}
}
void decode(char *buf,int n) {
for(int i = 0;i < n;i++) {
buf[i]--;
}
}
int main(int argv,char *argv[]) {
if(argv != 4) {
printf("use xx.exe -d[-c] src dest
");
exit(-1);
}
FILE *pfr = fopen(argv[2],"rb+");
if(pfr == NULL) {
exit(-1);
}
FILE *pfw = fopen(argv[3],"wb+");
if(pfw == NULL) {
fclose(pfr);
exit(-1);
}
int buf[1024];
int n;
if(strcmp(argv[1],"-c") == 0) {
while((n = fread((void *)buf,1,1024,pfr)) > 0) {
encode(buf,n);//加密函数
fwrite((void *)buf,1,n,pfw);
}
}else if(strcmpy(argc[1],"-d") == 0) {
while((n = fread((void *)buf,1,1024,pfr)) > 0) {
encode(buf,n);//加密函数
fwrite((void *)buf,1,n,pfw);
}
}else{
printf("arg error
");
}
fclose(pfr);
fclose(pfw);
return 0;
}
读写结构体的优势
结构体中的数据类型不统一,此时最适合用二进制的方式进行读写。二进制的接口可以读文本,而文本的接口不可以读二进制。
#include<stdio.h>
typedef struct student{
int num;
char name[30];
char sex;
float math;
float english;
float chinese;
}Stu;
int main() {
Stu s[5] = {
{1001,"assassin",'f',89,99,100},
{1002,"wunworld",'f',99,89,79},
{1003,"intelwisd",'m',98,80,100},
{1004,"seafwg",'m',99,90,99},
{1005,"xxxx",'f',90,99,100}
};//把初始化的内容写进结构体中,读出来。
//把数据以二进制形式保存,文本原样保存
FILE * pfs = fopen("stu.data","w+");
if(pfs == NULL) {
exit(-1);
}
for(int i = 0;i < 5;i++) {
fwrite((void *)&s[i],sizeof(Stu),1,pfs);//注意&s[i],对数组取地址
}
fclose(pfs);
return 0;
}
为什么结构体采用fread/fwrite来都写?
1.结构体数据类型不统一
2.可以将二进制转化为文本,降低效率,占用多余的存储空间。
读文件:
#include<stdio.h>
typedef struct student{
int num;
char name[30];
char sex;
float math;
float english;
float chinese;
}Stu;
int main() {
Stu s[5] = {
{1001,"assassin",'f',89,99,100},
{1002,"wunworld",'f',99,89,79},
{1003,"intelwisd",'m',98,80,100},
{1004,"seafwg",'m',99,90,99},
{1005,"xxxx",'f',90,99,100}
};//把初始化的内容写进结构体中,读出来。
//把数据以二进制形式保存,文本原样保存
FILE * pfw = fopen("stu.data","w+");
if(pfw == NULL) {
exit(-1);
}
Stu s;
while(fread((void *)&s,sizeof(Stu),1,pfw)) {
printf("num = %d
",s.num);
printf("name = %s
",s.name);
printf("sex = %c
",s.sex);
printf("math = %.2f
",s.math);
printf("english = %.2f
",s.english);
printf("chinese = %.2f
",s.chinese);
}
fclose(pfw);
return 0;
}
假如以小空间来读大数据的情况,在while循环中使用循环,通过循环的小标逐渐读出数据
#include<stdio.h>
typedef struct student{
int num;
char name[30];
char sex;
float math;
float english;
float chinese;
}Stu;
int main() {
Stu s[5] = {
{1001,"assassin",'f',89,99,100},
{1002,"wunworld",'f',99,89,79},
{1003,"intelwisd",'m',98,80,100},
{1004,"seafwg",'m',99,90,99},
{1005,"xxxx",'f',90,99,100}
};//把初始化的内容写进结构体中,读出来。
//把数据以二进制形式保存,文本原样保存
FILE * pfw = fopen("stu.data","w+");
if(pfw == NULL) {
exit(-1);
}
Stu s[3];//有3个,结构体有5个
while(fread((void *)&s,sizeof(Stu),1,pfw)) {
for(int i = 0;i < n;i++) {
printf("num = %d
",s[i].num);
printf("name = %s
",s[i].name);
printf("sex = %c
",s[i].sex);
printf("math = %.2f
",s[i].math);
printf("english = %.2f
",s[i].english);
printf("chinese = %.2f
",s[i].chinese);
}
}
fclose(pfw);
return 0;
}
实践:将链表作为内存数据模型,见文件作为数据库,将终端作为交互界面。读文件生成链表,修改链表写入文件。
//1.初始化数据库,此时的数据库是文件
//2.都数据库,生成内存数据模型,链表
//3.增,查,改,删,排序
//4.更新数据库
typedef struct student
{
char name[30];
char sex;
int age;
float score;
}Stu;
typedef struct _StuNode
{
Stu data;
struct _StuNode *next;
}StuNode;
void initData2File()
{
Stu s[4] =
{
{"assassin",'f',30,100},
{"wunworld",'f',27,79},
{"intelwisd",'m',25,100},
{"seafwg",'m',23,99},
{"xxxx",'f',23,100}
}
FILE *pf = fopen("stu.data","w+");
if(NULL == pf)
exit(-1);
fwrite((void *)s,sizeof(s),1,pf);
fclose(pf);
return ;
}
StuNode *createListFromFile(char *filePath)
{
FILE *pf = fopen(filePath,"r+");//格式写正确不然一不小心会覆盖
if(NULL == pf)
exit(-1);
StuNode *head = (StuNode *)malloc(sizeof(StuNode));
head->next = NULL;
StuNode *cur = (StuNode *)malloc(sizeof(StuNode));
while(fread((void *)&cur->data,sizeof(Stu),1,pf) )
{
cur->next = head->next;
head->next = cur;
cur = (StuNode *)malloc(sizeof(StuNode));
}
free(cur);
return head;
}
void traverseStuList(StuNode *head)
{
printf("name sex age score
");
head = head->next;
while(head)
{
printf("%-10s %c %d %.2f
",head->data.name,head->data.sex,head->data.age,head->data.score);
head = head->next;
}
}
void addListStuNode(StuNode *head)
{
StuNode *cur = (StuNode *)malloc(sizeof(StuNode));
printf("name:
");
scanf("%s",cur->data.name);
getchar();
printf("sex:
");
scanf("%c",&cur->data.sex);
getchar();
printf("age:
");
scanf("%sd",&cur->data.age);
getchar();
printf("score:
");
scanf("%f",c&ur->data.score);
cur->next = head->next;
head->next = cur;
}
StuNode * searchListStu(StuNode *head)
{
char name[30];
printf("pls input your search name:");
scanf("%d",name);
head = head->next;
while(head)
{
if(strcmp(head-data.name,name) == 0)
break;
head - head->next;
}
return head;
}
//删除操作
void deleteListNodeStu(StuNode *head)
{
StuNode *pfind = searchListStu(head);
if(pfind == null)
{
printf("你所要删除的人不存在!
");
return ;
}
while(head->next != pfind)
{
head = head->next;//找到前驱
}
head->next = pfind->next;
free(pfind);
return ;
}
//
int lenListStu(StuNode *head)
{
int len;
head = head->next;
while(head)
{
len++;
head = head->next;
}
return len;
}
void sortListStu(StuNode *head)
{
int len = lenListStu(head);
StuNode *prep,*p,*q;
for(int i = 0;i < len-1;i++)
{
prep = head;
p = prep->next;
q = q->next;
for(int j = 0;j < len-1-i;j++)
{
if(strcmp(p->data.name,q->data.name) > 0)
{
prep->next = q;
p->next = q->next;
q->next = p;
prep = q;
q = p->next;
continue;
}
prep = prep->next;
p = p->next;
q = q->next;
}
}
}
void saveList2FileStu(StuNode *head,char *filePath)
{
FILE *pf = fopen(filePath,"w+");
if(NULL == pf)
exit(-1);
head = head->next;
while(head)
{
fwrite((void *)&head->data,sizeof(Stu),1,pf);
head =head->next;
}
fclose(pf);
}
void destoryListStu(head)
{
StuNode *t;//找个替身
while(head)
{
t = head;
head = head->next;
free(t);
}
}
int main()
{
//initdata2File();
StuNode *head = createListFromFile("stu.data");
/*
traverseStuList(head);
printf("1->add 2->search 3->delete 4->exit
");
int choice;
scanf("%d",&choice);
switch(choice)
{
case 1:
addListStuNode(head);
break;
case 2:
break;
case 3:
break;
case 4:
break;
default:
printf("你输入错误!
");
}*/
StuNode *pfind;
while(1)
{
system("cls");//系统清屏
traverseStuList(head);
printf("1->add 2->search 3->delete 4->exit
");
int choice;
scanf("%d",&choice);
switch(choice)
{
case 1:
addListStuNode(head);
break;
case 2:
if(pfind = searchListStu(head))
{
printf("%-10s %c %d %.2f
",pfind->data.name,pfind->data.sex,pfind->data.age,pfind->data.score);
}
else
{
printf("没有此人!
");
}
break;
case 3:
deleteListNodeStu(head);
break;
case 4:
sortListStu(head);
break;
case 5:
saveList2FileStu(head,"stu.data");
destoryListStu(head);
return 0;
default:
printf("你输入错误!
");
}
}
}
文件偏移
int main()
{
FILE *pf = fopen("xxx.txt","w=");
fputs("abcdefg",pf);
int n = ftell(pf);//
printf("n = %d
",n);//n = 7,ftell(),求字节的大小
rewind(pf);//将文件重新指针向一个流的开头
n = ftell(pf);
printf("n = %d
",n);//0
feek(pf,0,SEEK_END);//操作文件pf,从SEEK_END末尾偏移0个单位。
n = ftell(pf);
printf("n = %d
",n);//7
feek(pf,0,SEEK_SET);//从头偏移0个
n = ftell(pf);
printf("n = %d
",n);//0
feek(pf,1,SEEK_CUR);//从当前位置偏移一个单位
n = ftell(pf);
printf("n = %d
",n);//0
return 0;
}