首页 > 其他分享 >【C/Cpp】文件操作

【C/Cpp】文件操作

时间:2024-01-16 19:00:29浏览次数:23  
标签:文件 stream int char pf FILE Cpp 操作

数据要进行持久化存储就需要用到文件。C/C++ 将文件看作有序的字节流,每个文件都是以 EOF(文件结束标志)结束。

按数据的组织形式,文件可分为文本文件和二进制文件。
数据在内存中以二进制形式存储的,如果不加转换地输出到外存,就是二进制文件。如果要求在外存上以 ASCII 码形式存储,需要在存储前进行转换。以ASCII 字符的形式存储的文件是文本文件。

  • 字符一律以 ASCII 形式存储
  • 数据型数据既可以用 ASCII 形式存储,也可以使用二进制形式存储。
    例如:整数 12345,如果以 ASCII 码的形式存储输出到磁盘,则占用5个字节,而以二进制形式输出,则在磁盘上只占4个字节。

在 C 语言中,流(stream)可以被视为一种特殊的数据结构,它负责在程序和外部设备(如键盘,显示器,文件等)之间进行数据传输。

C语言提供了标准流方便进行输入输出操作。C/C++ 程序在启动时,默认打开3个流:

  • stdin: 标准输入流,一般从键盘输入
  • stdout: 标准输出流,一般输出至控制台
  • stderr: 标准错误流,一般输出到控制台
    这三个流的类型都是 FILE*,通常称为文件指针。
    C/C++中就是通过文件指针来维护流的各种操作的。

文件指针

每个打开的文件都在内存中开辟一块区域,用来存放文件的相关信息(如文件名称,文件状态,文件当前位置等),这些信息是保存在一个 FILE 类型的结构体变量中的。

struct _iobuf {
    char *_ptr;
    int _cnt;
    char *_base;
    int _flag;
    int _file;
    int _charbuf;
    int _bufsiz;
    char *_tmpfname;
  };
typedef struct _iobuf FILE;

一般通过 FILE* 指针来维护该结构体变量,通过文件指针能间接找到它关联的文件。

文件操作函数

文件的操作步骤:

  1. 打开文件
  2. 对文件进行读、写操作
  3. 使用完文件后要关闭文件

打开文件 fopen() 和 关闭文件 fclose()

打开文件,fopen() 函数的声明:

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

参数:

  • filename: 文件名。默认为当前工作目录,可以指定路径,如:"D:\file\data.txt"
  • mode: 文件打开模式,即文件访问的权限

文本文件打开模式:

  • "r" : 只读,文件必须存在
  • "w" : 只写,会覆盖原内容,文件不存在会新建文件
  • "a" : 只写,写入数据会被附加到文件末尾,文件不存在会新建文件
  • "r+" : 读/写,文件必须存在
  • "w+" : 读/写,写会覆盖原内容,文件不存在将新建文件
  • "a+" : 读/写,写入数据会被附加到文件末尾,文件不存在会新建文件
    二进制文件打开模式:"rb"、"wb"、"ab"、"rb+"、"wb+"、"ab+"。

关闭文件,fclose() 的声明:

int fclose(FILE* stream);

使用方式:

FILE *in, *out;
in = fopen("data.in", "r");
out = fopen("data.out", "w");
//读、写操作
fclose(in);
fclose(out);

对文件进行读/写操作

文件光标操作

fseek()

移动光标。

int fseek(FILE* stream, long offset, int origin);

参数:

  • stream: 指明要操作的文件
  • offset: 偏移量,以字节为单位
  • origin: 偏移的起始位置
    • SEEK_SET:文件开始位置
    • SEEK_CUR:光标当前位置
    • SEEK_END: 文件末尾

rewind()

光标偏移到文件头。

void rewind(FILE* fp);

feof()

判断光标是否在文件末尾。

int feof(FILE* stream);

返回值: 当光标在文件尾时返回非零值,不是返回0。

ftell()

获取光标位置

long ftell(FILE* fp);

例如,测算文件大小

fseek(fp, 0L, SEEK_END);
int size = ftell(fp);

字符输入 fgetc() 和输出 fputc()

fgetc()从指定的流获取一个字符,并将位置标识符往前移动,声明:

int fgetc(FILE* stream);

参数:

  • stream: 文件,要被读取的流
    返回值:以无符号 char 强制转换为 int 的形式返回读取的字符,如果到达文件末尾或发生错误,则返回 EOF。

fputc()把参数 char 指定的字符写入到指定的流中,并将位置标识符往前移动,声明:

int fputc(int char, FILE* stream); 

参数:

  • char: 要写入的字符,以对应的 int 值进行传递
  • stream: 文件指针,要被写入字符的流

举例:

#include <cstdio>

int main()
{
  FILE* pfread = fopen("data1.txt", "r");
  if (pfread == nullptr)
  {
    perror("fopen->data1.txt");//打开data1.txt失败
    return 1;
  }
  FILE* pfwrite = fopen("data2.txt", "w");
  if (pfwrite == nullptr)
  {
    fclose(pfread);//关闭data1.txt
    pfread = nullptr;//释放pread的空间
    perror("fopen->data2.txt");//打开data2.txt失败
    return 1;
  }
  //数据的读写(拷贝)
  int ch = 0;
  while ((ch = fgetc(pfread)) != EOF)
  {
    fputc(ch, pfwrite);
  }
  fclose(pfread);
  fclose(pfwrite);
  return 0;
}

文本行输入 fgets() 和输出 fputs()

fgets() 函数声明:

char* fgets(cahr* buf, int max_count, FILE* stream);

参数:

  • buf: 字符数组指针,该数组存储要读取的字符串
  • max_count: 要读取的最大字符数。
  • stream: 要被读取的流
    返回值:读取到的字符串,读完后再读返回值是 NULL。
    fgets() 从 stream 中读取字符串,并将字符串存入 buf 中。当读取到 max_count-1 个字符时,或者读取到换行符时,或者到达文件末尾时,它会停止。

fputs() 声明:

int fputs(const char* str, FILE* steam);

参数:

  • str: 要写入的字符串
  • stream : 要被写入的流
    返回值:成功写入返回非负值,失败返回EOF。

举例:

#include <cstdio>
#include <iostream>

int main() {
    FILE *pf = fopen("data.txt", "w+");
    if(pf == nullptr) {
        return 1;
    }
    //写文件。fputs不会自动换行
    fputs("abcd\n", pf);
    fputs("efgh\n", pf);
    rewind(pf);
    //读取
    char buf[20];
    fgets(buf, 20, pf);
    std::cout << buf;
    fclose(pf);
    pf = nullptr;
    return 0;
}

格式化输入 fscanf() 和输出 fprintf()

使用方法类似 scanf()printf()。格式化输入 fscanf() 和输出 fprintf()声明:

int fscanf(FILE* stream, const char* format, ...);

int fprintf(FILE* stream, const char* format, ...);

举例:

#include <iostream>

struct Stu
{
    int num;
    char name[20];
    char sex;
    int age;
};
int main()
{
    Stu s{0};
    FILE* pf = fopen("data.txt", "r");
    if (pf == nullptr) {
        return 1;
    }
    //写读文件
    fscanf(pf, "%d%s %c%d", &s.num, s.name, &s.sex, &s.age);
    fprintf(stdout, "%d %s %c %d\n", s.num, s.name, s.sex, s.age);
    fclose(pf);
    pf = nullptr;
    return 0;
}

二进制输入 fread() 和输出 fwrite()

fread() 从给定流 stream 读取数据到 _DstBuf 所指向的空间,声明:

size_t fread(void* _DstBuf,size_t _ElementSize,size_t _Count,FILE* stream);

参数:

  • _DstBuf:指向一块内存空间的指针,其大小至少为_ElementSize*_Count 字节
  • _ElementSize: 要读取的每个元素的大小,以字节为单位
  • _Count: 要读取的元素个数
  • stream: 输入流

fwrite() 将 _Str 所指向的数据写入到给定流 stream 中,声明:

size_t fwrite(const void* _Str,size_t _Size,size_t _Count,FILE* stream);

参数:

  • _Str: 指向被写入的数据的指针
  • _Size: 要被写入的每个元素的大小,以字节为单位
  • _Count: 要读取的元素个数
  • stream: 输出流

举例

#include <iostream>

struct Stu
{
    int num;
    char name[20];
    char sex;
    int age;
};

int main()
{
    Stu s1[3] = {1, "HH", 'M', 20,
                2, "ZZ", 'M', 21,
                3, "YY", 'M', 19,};
    Stu *s2 = (Stu*)malloc(sizeof(s1[0]) * 3);
    FILE* pf = fopen("data.txt", "wb+");
    if (pf == nullptr)
    {
        return 1;
    }
    //二进制的形式读写文件
    fwrite(s1, sizeof(s1[0]), 3, pf);
    rewind(pf);
    fread(s2, sizeof(s1[0]), 3, pf);
    for (int i = 0; i < 3; i++) {
        printf("%d %s %c %d\n", (s2+i)->num, (s2+i)->name,
               (s2+i)->sex, (s2+i)->age);
    }
    fclose(pf);
    pf = nullptr;
    return 0;
}

freopen 函数

freopen 函数将 filename 所指文件与给定的 stream 流关联起来,主要用来重定向标准流。freopen() 函数的声明:

FILE* freopen(const char* filename, const char* mode, FILE* stream);

参数:

  • filename: 要打开文件的名称
  • mode: 文件打开模式,即文件访问的权限
  • stream: 文件要关联的流,通常是标准文件流(stdin/stdout)或标准错误输出流(stderr)
    返回值:成功则返回关联的 stream 指针

使用方式:

#include <cstdio> //freopen 所在头文件
#include <iostream>

using namespace std;
int main() {
    int x, y;
    freopen("data.in", "r", stdin); //以只读模式打开文件,并重定向stdin
    freopen("data.out", "w", stdout);//以只写模式打开文件,并重定向stdout
    
    //使用 printf/scanf/cin/cout
     cin >> x >> y; //从 data.in 读取数据到 x 和 y
     cout << x +y; //把 x+y 的结果写入 data.out
     fclose(stdin); //关闭输入流
     fclose(stdout); //关闭输出流
     return 0;
}

printf/scanf/cin/cout 等函数默认使用 stdin/stdout,将 stdin/stdout 重定向后,这些函数将输入/输出到被定向的文件。

ifstream/ofstream 文件输入输出流

C++ 提供了 ifstream 和 ofstream 来两个文件流用于进行文件输入输出操作

#include <fstream>
using namespace std;  // 两个类型都在 std 命名空间里

int main() {
    char data[100];
    //以读模式打开文件
    ifstream fin("in.txt");
    //以写模式打开文件
    ofstream fout("out.txt");
    //读取,写入操作类似cin/cout
    fin.getline(data, 100);
    fout << data;
    //关闭流
    fin.close();
    fout.close();
    return 0;
}

标签:文件,stream,int,char,pf,FILE,Cpp,操作
From: https://www.cnblogs.com/hzyuan/p/17968344

相关文章

  • 中国互联网有哪些地方会被卡脖子:操作系统篇
    在互联网领域,中美实力都很强大,那么中国相比美国到底差距在哪里?回顾历史,我们可以发现,中国互联网起步在2000年左右,而美国在此之前已经发展了20年,正是这20年,让美国占据了先发优势。那么,美国有哪些先发优势呢?操作系统先来的吃肉,后到的就只能喝汤了。操作系统作为计算机领域非常重......
  • 文件预览方案
    原文链接:全网最全的docx、pptx、xlsx、pdf文件预览方案(典藏版)花钱解决(使用市面上现有的文件预览服务)微软(https://view.officeapps.live.com/op/view.aspx?src=${encodeURIComponent(url)})google阿里云IMMXDOCOfficeWeb365wps开放平台前端方案pptx的预览方案pdf......
  • python获取当前执行py文件的路径
    1.os.getcwd() 只有路径,不包含py文件名path=os.getcwd()print(path)#结果:E:\pyworkspace\pycharmProjects\cdtest\oproject\Pubic 2.os.path.realpath(__file__)#包含了py文件path=os.path.realpath(__file__)print(path)#结果:E:\pyworkspace\pycharmProjects\c......
  • Vue加element Ui 实现下载文件和进度条展示
    <template><el-progress:percentage="percentage"></el-progress><h1>{title}</h1><el-button:disabled="isDisabled"@click="getProgress">下载文件</el-button></template>......
  • docker 操作手册(三)镜像打包
    保存镜像dockerimagesave--helpSaveimage(s)toanarchiveDescription:Saveanimagetodocker-archiveoroci-archiveonthelocalmachine.Defaultisdocker-archive.Usage:dockerimagesave[options]IMAGE[IMAGE...]Examples:podmanimagesave......
  • 【python网络编程相关】 ----操作系统相关了解
    title:【python网络编程相关】----操作系统相关了解date:2024-01-1615:54:06updated:2024-01-1616:20:00description:【python网络编程相关】----操作系统相关了解cover: https://www.cnblogs.com/YZL2333/p/10444200.htmlhttps://home.cnblogs.com/u/......
  • 关于修改prometheus-operator 方式下的prometheus的配置文件
    fq简单介绍prometheus-operator中的每个PrometheusCRD资源,Operator都会以StatefulSet形式在相同的命名空间下部署对应配置的资源,PrometheusPod的配置是通过一个包含Prometheus配置的名为的Secret对象声明挂载的。该CRD根据标签选择来指定部署的Prometheus实......
  • 国标视频监控平台EasyCVR如何通过接口调用下载设备录像文件
    安防监控系统国标GB28181协议EasyCVR视频监控平台采用了开放式的网络结构,平台可支持Windows/Linux(CentOSubuntu)/国产麒麟系统,能在局域网、公网、专网等复杂的网络环境中,将场景中分散的海量网络监控设备进行统一接入与汇聚管理,并能提供实时远程视频监控、视频录像、回放与存储、......
  • C++---打开txt文件进行字符串的查找替换最终生成Excel文件
    #include<iostream>#include<fstream>#include<sstream>#include<string>#include<vector>#include<algorithm>#include<iomanip>usingnamespacestd;voidfindAndReplaceAll(string&source,conststring&......
  • 52.数据库操作
    数据库操作数据库操作是每一门编程语言中都必不可少的操作。使用程序操作数据库之前,需要在本地或服务器先安装数据库,比如MySQL数据库。Python中使用第三方模块PyMySQL操作数据库,使用前需要先进行安装。安装PyMySQLpipinstallpymysql操作流程使用 PyMySQL 模块......