C File Operation

C标准库 操作文件

数据持久化的两种方法:文件和数据库

文本文件和二进制文件

举个例子,写C++的代码,源代码为文本文件、编译出来的可执行文件(.exe)文件是二进制文件

文本文件

以文本的编码(ASCII码、UNICODE编码等)形式存储在计算机中。它是以”行”为基本结构的一种信息组织和存储方式。

文本文件是基于字符编码的文件,基本上是定长的,译码容易些

二进制文件

文本的二进制形式存储在计算机中,用户一般不能直接读懂它们,只有通过相应的软件才能将其显示出来。

二进制文件编码是变长的,所以它灵活,存储利用率要高些,译码难一些(不同的二进制文件格式,有不同的译码方式)

二进制文件一般是可执行程序、图形、图像、声音等等。

C标准库操作文件的函数fopen(打开)fclose(关闭)

fopen()函数


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

其中第一个参数为文件路径,第二个参数为打开模式

成功返回I/O流指针,作为后续I/O流函数的参数

失败返回NULL

打开模式

打开模式作用作用
r只读文件必须存在,从头开始读
w只写文件不存在就创建,文件存在就清空内容,从头开始写
a追加文件不存在就创建,文件存在就在文件尾开始写
r+读写文件必须存在,从头开始读写
w+写读文件不存在就创建,文件存在就清空内容,从头开始写读
a+追读文件不存在就创建,文件存在就在文件尾开始写,从头开始读

fclose()函数


int fclose(FILE * fp)

参数为I/O流指针

成功返回0,失败返回EOF(End Of File)

操作文件的步骤

  • 声明文件I/O流指针
  • 打开文件
  • 对文件的操作
  • 关闭文件,I/O流指针置为NULL

#include "stdio.h"

int main(){
    FILE *fp = NULL;        //声明I/O流指针
    fp = fopen("./1.txt","r");  //打开文件
    //对文件的操作
    ………………
    fclose(fp); //关闭文件
    fp = NULL;  //  I/O流指针置为NULL
}

格式化I/O

格式化输出


int fprintf(
    FILE* stream ,      //I/O流指针
    const char * format,    //格式化字符串
    ……                  //输出数据
)

fprintf(fp,"%d",520); #输出到fp指代的文件中

#include "stdio.h"
int main(){
    FILE *fp = NULL;    //声明I/O流指针
    fp = fopen("./test.txt","w+");  //打开文件,写读

    fprintf(fp,"%s %d","清光照归途",520);        //将"清光照归途 520"写入文件中

    fclose(fp);     //关闭文件
    fp = NULL;      //I/O流指针置NULL

    return 0;
}

格式化输入


int fscanf(
    FILE* stream ,      //I/O流指针
    const char * format,    //格式化字符串
    ……                  //输出数据
)

fscanf(fp,"%d",&num); #把从文件中读取到的数据放入num中

#include "stdio.h"
int main(){
    FILE *fp = NULL;    //声明I/O流指针
    //fp = fopen("./test.txt","w+");    //打开文件,写读
    fp = fopen("./test.txt","r");   //打开文件,读

    //fprintf(fp,"%s %d","清光照归途",520);      //将"清光照归途 520"写入文件中
    char str[101];
    int num ;       //str和num用于存放从文件中读取的数据
    fscanf(fp,"%s %d",str,&num);
    printf("读取到的内容为:%s %d",str,num);

    fclose(fp);     //关闭文件
    fp = NULL;      //I/O流指针置NULL

    return 0;
}

二进制I/O

二进制输入


size_t fwrite(const void* ptr ,     // 缓存区地址

    size_t size,                //元素字节数

    size_t number,          //期望输出的元素数

    FILE* stream            //I/O流指针
)

例如:int a[9] = {0,1,2,3,4,5,6,7,8};


fwrite(a, sizeof(int), 9, fp); #将a数组写入至fp指向的文件中

#include "stdio.h"

int main(){
    FILE *fp = NULL;    //声明I/O流指针
    fp = fopen("./bin.dat","w+");   //打开文件,写读

    int a[9] = {0,1,2,3,4,5,6,7,8};
    fwrite(a,sizeof(int),9,fp);     //将a数组写入到fp指向的文件中

    fclose(fp); //关闭文件
    fp = NULL;  //I/O流指针置NULL
    return 0;
}

二进制输出


size_t fread(const void* ptr ,     // 缓存区地址

    size_t size,                //元素字节数
    size_t number,          //期望输出的元素数
    FILE* stream            //I/O流指针
)

fread(a, sizeof(int), 9, fp); #从fp指向的文件中读取数据放入a中

#include "stdio.h"
int main(){
    FILE *fp = NULL;    //声明I/O流指针
    //fp = fopen("./bin.dat","w+"); //打开文件,写读
    fp = fopen("./bin.dat","r");    //打开文件,读

    //int a[9] = {0,1,2,3,4,5,6,7,8};
    int buffer[9];  //缓存区地址
    fread(buffer,sizeof(int),9,fp);     //将文件内容读取到buffer
    for(int i=0; i < 9; i++){
        printf("%d ", buffer[i]);
    }
    fclose(fp); //关闭文件
    fp = NULL;  //I/O流指针置NULL
    return 0;
}

文件读写位置

设置文件读写位置


int fseek(    FILE* stream,//I/O流指针
            long offset, //偏移字节数
            int whence, //偏移起点
            (SEEK_SET文件头 ,SEEK_CUR当前位置,SEEK_END文件尾)
)

成功返回0,失败返回-1

例如:fseek(fp,8,SEEK_SET)从fp文件头开始往后数8字节的位置开始

fseek(fp,-12,SEEK_END)从fp文件尾开始往前数12字节的位置开始

获取文件操作位置

long feel(FILE *stream)参数为I/O流指针

成功返回当前文件位置,失败返回-1

 
#include "stdio.h"
int main(){
    FILE *fp = NULL;    //声明I/O流指针
    //fp = fopen("./bin.dat","w+"); //打开文件,写读
    fp = fopen("./bin.dat","r");    //打开文件,读
    fseek(fp,8,SEEK_SET);
    long lac1 = ftell(fp);
    printf("初始文件位置:%ld\n",lac1);
    //int a[9] = {0,1,2,3,4,5,6,7,8};
    int buffer[9] = {0};    //缓存区地址
    fread(buffer,sizeof(int),9,fp);     //将文件内容读取到buffer
    for(int i = 0;i<9;i++){
        printf("%d ",buffer[i]);
    }
    long lac2 = ftell(fp);
    printf("\n结束文件位置:%ld",lac2);
    fclose(fp); //关闭文件
    fp = NULL;  //I/O流指针置NULL
    return 0;
}

//运行结果
初始文件位置:8
272 3 4 5 6 7 8 0 0
28结束文件位置:36 // 8 + ( 7 * 4 ) = 36