Bootstrap

C++ 结构体数据读写文件 fopen fclose fwrite wread fseek函数详情

1.头文件

#include <stdio.h>

2.fopen()函数

调用fopen()函数可以打开或创建一个文件。

FILE *fopen(const char *path, const char *mode);

path : 参数 path 指向文件路径,可以是绝对路径、也可以是相对路径。

mode : 参数 mode 指定了对该文件的读写权限,是一个字符串。

返回值: 调用成功返回一个指向 FILE 类型对象的指针( FILE * ),该指针与打开或创建的文件相关联, 后续的标准 I/O 操作将围绕 FILE 指针进行。如果失败则返回 NULL ,并设置 errno 以指示错误原因。

3.fread()函数

当使用 fopen() 库函数打开文件之后,我们便可以使用 fread() 库函数对文件进行读操作

size_t fread(void *ptr, size_t size, size_t nmemb, FILE *stream);

ptr:fread()将读取到的数据存放在参数 ptr 指向的缓冲区中;

size:fread()从文件读取 nmemb 个数据项,每一个数据项的大小为 size 个字节,所以总共读取的数据大小为 nmemb * size 个字节。

nmemb:参数 nmemb 指定了读取数据项的个数。

stream:FILE 指针。

返回值:调用成功时返回读取到的数据项的数目(数据项数目并不等于实际读取的字节数,除非参数 size 等于 1);如果发生错误或到达文件末尾,则 fread()返回的值将小于参数 nmemb,那么到底发生了错误 还是到达了文件末尾,fread()不能区分文件结尾和错误,究竟是哪一种情况,此时可以使用 ferror()或 feof() 函数来判断。

4.fwrite()函数

对文件进行写操作

size_t fwrite(const void *ptr, size_t size, size_t nmemb, FILE *stream);

ptr : 将参数 ptr 指向的缓冲区中的数据写入到文件中。

size : 参数 size 指定了每个数据项的字节大小,与 fread() 函数的 size 参数意义相同。

nmemb : 参数 nmemb 指定了写入的数据项个数,与 fread() 函数的 nmemb 参数意义相同。

stream : FILE 指针。

返回值: 调用成功时返回写入的数据项的数目(数据项数目并不等于实际写入的字节数,除非参数 size 等于 1 );如果发生错误,则 fwrite() 返回的值将小于参数 nmemb (或者等于 0 )。

5.fclose()函数

调用 fclose()库函数可以关闭一个由 fopen() 打开的文件。

int fclose(FILE *stream);

参数 stream 为 FILE 类型指针,调用成功返回 0 ;失败将返回 EOF (也就是 -1 ),并且会设置 errno 来指示错误原因。

可以根据函数的返回值判断文件是否关闭成功。

6.打开文件标识说明:

 文件使用方式由r,w,a,t,b,+六个字符拼成,各字符的含义是:

r(read): 读

w(write): 写

a(append): 追加

t(text): 文本文件,可省略不写

b(banary): 二进制文件

+: 读和写

组合含义:

"r" 打开一个用于读取的文件。该文件必须存在。

"w" 创建一个用于写入的空文件。如果文件名称与已存在的文件相同,则会删除已有文件的内容,文件被视为一个新的空文件。

"a" 追加到一个文件。写操作向文件末尾追加数据。如果文件不存在,则创建文件。

"r+" 打开一个用于更新的文件,可读取也可写入。该文件必须存在。

"w+" 创建一个用于读写的空文件。

"a+" 打开一个用于读取和追加的文件。

"rt" 只读打开一个文本文件,只允许读数据

"wt" 只写打开或建立一个文本文件,只允许写数据

"at" 追加打开一个文本文件,并在文件末尾写数据

"rb" 只读打开一个二进制文件,只允许读数据

"wb" 只写打开或建立一个二进制文件,只允许写数据

"ab" 追加打开一个二进制文件,并在文件末尾写数据

"rt+" 读写打开一个文本文件,允许读和写

"wt+" 读写打开或建立一个文本文件,允许读写

"at+" 读写打开一个文本文件,允许读,或在文件末追加数据

"rb+" 读写打开一个二进制文件,允许读和写

"wb+" 读写打开或建立一个二进制文件,允许读和写

"ab+" 读写打开一个二进制文件,允许读,或在文件末追加数据

补充:

(1)二进制标志,文本标志,在linux下是没有区别的

(2)可以用hexdump -C 文件名 命令查看二进制文件的十六进制编码

6.fseek函数

作用:调节文件指针位置,用来设置打开文件中光标的位置。

int fseek(FILE * _File, long _Offset, int _Origin);

_File:为文件指针。

offset:为偏移量,正数表示正向偏移,负数表示负向偏移。

origin:设定从文件的哪里开始偏移,可能取值为:SEEK_CUR、SEEK_END或SEEK_SET。

备注

SEEK_CUR

1

当前位置(文件指针的原本位置)

SEEK_END

2

末尾

SEEK_SET

0

开头

7.ftell函数

ftell函数用于得到文件位置指针当前位置相对与文件首的偏移字节数。在随机方式存取文件时,由于文件位置频繁的前后移动,程序不容易确定文件的当前位置。

long len = ftell(fp)

8.使用案例(QT)

结构体:

struct Student
    {
        char number[20];
        char name[20];
        int age;
        bool isman;
        char phone[13];
        char like[64];
    };

写入数据

    Student student;
    memset(&student, 0, sizeof(Student));

    strcpy(student.number,"20170856");
    strcpy(student.name,"张三");
    student.age = 20;
    strcpy(student.phone,"17765852634");
    strcpy(student.like,"睡觉睡觉睡觉睡觉睡觉");
    student.isman = true;

    FILE *fp = fopen("test", "w+");
    int size = fwrite((char *)&student, 1, sizeof(Student), fp);
    if(size)
    {
        qDebug()<<"数据保存成功。";
    }
    fclose(fp);

读取数据:

    FILE *fp = fopen("test", "r");
    Student student;
    int size = fread((char*)&student, 1, sizeof(Student), fp);
    qDebug()<<size;
    fclose(fp);

    ui->textEdit->append(QString("number:%1").arg(student.number));
    ui->textEdit->append(QString("name:%1").arg(student.name));
    ui->textEdit->append(QString("isman:%1").arg(student.isman));
    ui->textEdit->append(QString("age:%1").arg(student.age));
    ui->textEdit->append(QString("phone:%1").arg(student.phone));
    ui->textEdit->append(QString("like:%1").arg(student.like));

批量数据的写入和读取

    //写入
    Student student;
    memset(&student, 0, sizeof(Student));
    strcpy(student.number,"20170856");
    strcpy(student.name,"张三");
    student.age = 20;
    strcpy(student.phone,"17765852634");
    strcpy(student.like,"睡觉睡觉睡觉睡觉睡觉");
    student.isman = true;
    FILE *fp = fopen("test", "w+");

    for(int i = 0;i<15;i++)
    {
        student.age += i;
        int size = fwrite((char *)&student, 1, sizeof(Student), fp);
        if(size)
        {
            qDebug()<<"数据保存成功。";
        }
    }

    fclose(fp);



    //读取
    FILE *fp = fopen("test", "r");
    fseek(fp,0,2);
    int size = ftell( fp ) / sizeof(Student);
    qDebug()<<size;
    fseek(fp,0,0);
    for(int i = 0;i<size;i++)
    {
        Student student;
        int size = fread((char*)&student, 1, sizeof(Student), fp);
        qDebug()<<size;
        
        ui->textEdit->append(QString("number:%1").arg(student.number));
        ui->textEdit->append(QString("name:%1").arg(student.name));
        ui->textEdit->append(QString("isman:%1").arg(student.isman));
        ui->textEdit->append(QString("age:%1").arg(student.age));
        ui->textEdit->append(QString("phone:%1").arg(student.phone));
        ui->textEdit->append(QString("like:%1").arg(student.like));
    }
    
    fclose(fp);

;