C/C++(文件操作二)

二进制读写才是本质

二进制的读写对文件标记不敏感。
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;
}
原文地址:https://www.cnblogs.com/intelwisd/p/8419953.html