021-C语言文件操作

C语言文件操作

文章目录

  • C语言文件操作
    • 1. 文件的概念
    • 2. 二进制文件和文本文件
    • 3. 文件的打开和关闭
      • 3.1 流和标准流
        • 3.1.1 流
        • 3.1.2 标准流
      • 3.2 文件指针
      • 3.3 文件的打开和关闭
    • 4. 文件的顺序读写
      • 4.1 顺序读写函数
      • 4.2 对比两组函数
        • 4.2.1 scanf/fscanf/sscanf
        • 4.2.2 printf/fprintf/sprintf
    • 5. 文件的随机读写
      • 5.1 fseek
      • 5.2 ftell
      • 6.3 rewind
    • 6. 文件读取结束的判定
      • 6.1 被错误使用的feof
      • 6.2 判断读取结束
    • 7. 文件缓冲区

1. 文件的概念

  • 文件的作用:

    文件是用来存储数据的,在之前写的代码中,只要我们对出程序,之前的数据就不复存在了,如果想要将数据保存到电脑上,就需要使用文件。

  • 文件的分类:程序文件、数据文件(从文件功能的角度来分类)

    • 程序文件:

      程序文件包括源程序文件(.c),目标文件(Windows下为.obj),可执行程序(Windows下为.exe)

    • 数据文件:

      内容不一定是程序,而是程序运行时读写的数据,比如程序允许需要从中读取数据的文件,或者输出内容的文件。

    • 文件标识:

      一个文件一定要有一个唯一的文件标识,以便识别和使用,文件标识分为三个部分:文件路径+文件名主干+文件后缀,例如:C:\code\test.c,为了方便起见,文件标识常被称为文件名

2. 二进制文件和文本文件

根据数据的组织形式,数据文件被称为文本文件二进制文件

数据在内存中以二进制的形式存储,如果不加转换的输出到外存,就是二进制文件。

如果要求外层加上ASCII码的形式存储,则需要在存储前进行转换。以ASCII字符的形式存储的文件就是文本文件。

存储的方式:字符一律以ASCII码形式存储,数值型数据既可以使用ASCII码形式存储,也可以使用二进制形式存储。

如果有一个整数10000,如果以ASCII码的形式输出到磁盘,则磁盘中占用5个字节(每一个字符一个字节),而二进制形式输出,则在磁盘上只占4个字节。

在这里插入图片描述

3. 文件的打开和关闭

3.1 流和标准流

3.1.1 流

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同大外部设备的输入输出操作各不相同,为了方便程序员对各种设备进行方便的错做,我们抽象出了流的概念。可以把流理解为一条流淌着字符的河流。

C程序针对文件、画面、键盘等的数据输入输出都是对流进行操作的。

一般情况下,我们想要向流里写数据,或者从流中读取数据,都是要打开流,然后操作。

3.1.2 标准流

我们发现,我们之前的程序中,向键盘输入数据,向屏幕上输出数据,并没有打开流。

那是因为C语言程序在启动的时候默认打开了3个流:

  • stdin - 标准输入流,大多数情况的环境中从键盘输入。
  • stdout - 标准输出流,大多数情况的环境中输出至显示屏。
  • stderr - 标准错误流,大多数情况的环境中输出至显示屏。

因为默认打开了这三个流,我们使用的scanf、printf等函数就可以直接进行输入输出操作。

stdinstdoutstderr这三个文件的类型是:FILE*,通常称为文件指针。

C语言中就是通过FILE*的文件指针来维护流的各种操作的。

3.2 文件指针

缓冲文件系统中,关键的概念是文件类型指针,简称文件指针

每个被使用的文件都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态,及文件当前的位置等)。这些信息是保存在一个结构体变量中的。该结构体类型是由系统声明的,取名为FILE

下面是VS2013编译环境中提供的stdio.h头文件中的文件类型声明。

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

不同的C编译器的FILE类型包含的内容不完全相同,但是大同小异(VS2022环境下的FILE类型和上面的似乎就不太一样)。

每当打开一个文件的时候,系统回根据文件的情况自动创建一个FILE结构的变量,并填充其中的信息,使用者不必关心细节。

一般都是通过一个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。

创建FILE*指针变量:

FILE* fp;

pf是一个指向FILE类型数据的指针变量。可以使某个pf指向某个文件的文件信息区(是一个结构体变量)。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够间接找到与它关联的文件

在这里插入图片描述

3.3 文件的打开和关闭

文件在读写之前应该要先打开文件,在使用结束后应该关闭文件

在编写程序的时候,在打开文件的同时,都会返回应该FILE*的指针变量指向该文件,也相当于建立了指针和文件的关系。

ANSIC规定使用fopen函数来打开文件,fclose函数来关闭文件。

FILE * fopen ( const char * filename, const char * mode );int fclose ( FILE * stream );
  • filename:需要打开的文件名。
  • stream:需要关闭的文件的文件指针。
  • mode:文件的打开模式,如下表。
文件使用方式含义如果指定文件不存在
“r”(只读)打开一个已经存在的文本文件,只进行读取数据出错
“w”(只写)打开一个文本文件,如果文件存在,清空文件中原来的内容,只进行写入数据建立新的文件
“a”(追加)打开一个文本文件,向文本文件末尾添加数据建立新的文件
“rb”(只读)打开一个二进制文件,只进行读取数据出错
“wb”(只写)打开一个二进制文件,如果文件存在,清空文件中原来的内容,只进行写入数据建立新的文件
“ab”(追加)打开一个文本文件,向文本文件末尾添加数据建立新的文件
“r+”(读写)打开一个文本文件,进行读写操作出错
“w+”(读写)打开一个文本文件,如果文件存在,清空文件中原来的内容,进行读写操作建立新的文件
“a+”(读写)打开一个文本文件,在文件末尾进行读写操作建立新的文件
“rb+”(读写)打开一个二进制文件,进行读写操作出错
“wb+”(读写)打开一个二进制文件,如果文件存在,清空文件中原来的内容,进行读写操作建立新的文件
“ab+”(读写)打开一个二进制文件,在文件末尾进行读写操作建立新的文件
#include <stdio.h>int main()
{// 打开文件FILE* pf = fopen("test.txt", "w");// 关闭文件if (pf != NULL)fclose(pf);return 0;
}

4. 文件的顺序读写

4.1 顺序读写函数

函数名功能适用于
fgetc字符输入函数所有输入流
fputc字符输出函数所有输出流
fgets文本行输入函数所有输入流
fputs文本行输出函数所有输出流
fscanf格式化输入函数所有输入流
fprintf格式化输出函数所有输出流
fread二进制输入函数文件
fwrite二进制输出函数文件

上面的适用于所有输入流一般指适用于标准输出流和其他输出流(如文件输入流),所有输出流一般指的是标准输出流和其他输出流(如文件输出流)

4.2 对比两组函数

4.2.1 scanf/fscanf/sscanf
int scanf ( const char * format, ... );
int fscanf ( FILE * stream, const char * format, ... );
int sscanf ( const char * s, const char * format, ...);
  • scanf:这个函数我们前面使用的很多,作用就是从标准输入流获取(一般是键盘)数据。
  • fscanf:从我们指定的流中获取数据,比如从某文件中获取数据,第一个参数传递文件指针即可,其他参数与scanf基本一致。
  • sscanf:从s字符串中获取数据,第一个参数传递字符串指针,其他参数与scanf基本一致。

上面三个函数的返回值:读取数据成功时,返回读取成功的总项数,读取数据失败时,返回EOF。

4.2.2 printf/fprintf/sprintf
int printf ( const char * format, ... );
int fprintf ( FILE * stream, const char * format, ... );
int sprintf ( char * str, const char * format, ... );
  • printf:这个函数在前面使用过很多次,作用就是将指定内容输出到标准输出流中(一般是屏幕)。
  • fprintf:将数据输出到指定的流中,比如输出到某文件,第一个参数传递文件指针即可,其他参数与printf基本一致。
  • sprintf:将数据输出到指定字符串中(写入到字符串中),第一个参数传递指定的字符串指针,其他参数与printf基本一致。

上面三个函数的返回值:输出成功时,则返回输出的总字符数,输出失败时,则返回一个负数。

5. 文件的随机读写

5.1 fseek

重新设置文件位置指示器。

文件位置指示器类似于我们的鼠标光标,当打开文件时,文件位置指示器位于文件的开头。

int fseek ( FILE * stream, long int offset, int origin );
  • stream:文件指针
  • offset:偏移量,决定将文件指示器移动至相对于origin位置多少偏移量的位置,正数在表向右移,负数代表向左移。
  • origin:移动文件指针的相对位置。
    • SEEK_SET:文件开头位置。
    • SEEK_CUR:文件指示器的当前位置。
    • SEEK_END:文件结尾位置。

注:库实现可以不真正支持 SEEK_END (因此,使用它的代码没有真正的标准可移植性)。

#include <stdio.h>int main()
{FILE* pFile;pFile = fopen("example.txt", "wb");fputs("This is an apple.", pFile);fseek(pFile, 9, SEEK_SET);fputs(" sam", pFile);fclose(pFile);return 0;
}

在这里插入图片描述

5.2 ftell

long int ftell ( FILE * stream );

stream:文件指针。

返回文件指针相对于起始位置的偏移量。

#include <stdio.h>
int main()
{FILE* pFile;long size;pFile = fopen("myfile.txt", "rb");if (pFile == NULL)perror("Error opening file");else{fseek(pFile, 0, SEEK_END); // non-portablesize = ftell(pFile);fclose(pFile);printf("Size of myfile.txt: %ld bytes.\n", size);}return 0;
}

在这里插入图片描述

在这里插入图片描述

6.3 rewind

void rewind ( FILE * stream );

让文件指针的位置回到文件的起始位置。

#include <stdio.h>
int main()
{int n;FILE* pFile;char buffer[27];pFile = fopen("myfile.txt", "w+");for (n = 'A'; n <= 'Z'; n++)fputc(n, pFile);rewind(pFile);fread(buffer, 1, 26, pFile);fclose(pFile);buffer[26] = '\0';printf(buffer);return 0;
}

在这里插入图片描述

6. 文件读取结束的判定

6.1 被错误使用的feof

int feof ( FILE * stream );

检查文件结束指示符。

当一个文件位置指示器读取数据尝试读取到文件末尾或之后时,文件结束指示符会被设置。

当结束指示符被设置时,feof将返回非零值,否则返回0;

当未到文件末尾时,读取就已经结束,这种情况文件结束指示符不会被设置,feof将返回0。

所以我们不能用feof判断读取是否结束。

6.2 判断读取结束

  1. 文本文件读取是否结束可以判断读取函数的返回值是否为EOF(如fgetc)或NULL(如fgets)。
  2. 二进制文件的读取结束判断,判断返回值是否小于实际要读的个数,如使用fread判断返回值是否小于实际要读的个数。

7. 文件缓冲区

ANSIC标准采用缓冲文件系统处理数据文件,所谓文件缓冲系统就是指系统自动在内存中为程序中每个正在使用的文件开辟一块文件缓冲区。从内存向磁盘输出数据会先送到内存中的缓冲区,装满缓冲区后才一起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件读取数据输入到内存缓冲区(充满缓冲区),然后再冲缓冲区逐个地将数据送到程序数据区(程序变量等)。缓冲区的大小根据C编译系统决定。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/903015.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何使用@KafkaListener实现从nacos中动态获取监听的topic

1、简介 对于经常需要变更kafka主题的场景&#xff0c;为了实现动态监听topic的功能&#xff0c;可以使用以下方式。 2、使用步骤 2.1、添加依赖 <dependency><groupId>org.springframework.kafka</groupId><artifactId>spring-kafka</artifactI…

《TCP/IP详解 卷1:协议》之第七、八章:Ping Traceroute

目录 一、ICMP回显请求和回显应答 1、ICMP回显请求 2、ICMP回显应答 二、ARP高速缓存 三、IP记录路由选项&#xff08;Record Route&#xff0c;RR&#xff09; 1、记录路由选项的工作过程 2、RR 选项的 IP 头部格式 2.1、RR 请求 2.2、RR响应 四、ping 的去返路径 五…

30天通过软考高项-第四天

30天通过软考高项-第四天 任务&#xff1a;项目进度管理 思维导图阅读 知识点集锦阅读 知识点记忆 章节习题练习 知识点练习 手写回忆ITTO 听一遍喜马拉雅关于范围的内容 进度管理-背 1. 过程定义 龟腚排池至控 规划进度管理&#xff1a;为了规划、编制、管理…

根据JSON动态生成表单表格

根据JSON动态生成表单表格 一. 子组件 DynamicFormTable.vue1,根据JSON数据动态生成表单表格,支持表单验证JS部分1.1,props数据1.2,表单数据和数据监听1.3,自动验证1.4,表单验证1.5,获取表单数据1.6,事件处理1.7,暴露方法给父组件2,HTML部分二,父组件1, 模拟数据2,…

【赵渝强老师】快速上手TiDB数据库

从TiDBv4.0起&#xff0c;提供了包管理工具TiUP&#xff0c;负责管理TiDB、PD、TiKV等组件。用户只需通过TiUP命令即可运行这些组件&#xff0c;显著降低了管理难度。TiUP程序只包含少数几个命令&#xff0c;用来下载、更新、卸载组件。TiUP通过各种组件来扩展其功能。组件是一…

springboot入门-DTO数据传输层

在 Spring Boot 应用中&#xff0c;DTO&#xff08;Data Transfer Object&#xff0c;数据传输对象&#xff09; 是专门用于在不同层&#xff08;如 Controller 层、Service 层、外部系统&#xff09;之间传输数据的对象。它的核心目的是解耦数据模型和业务逻辑&#xff0c;避免…

安装docker,在docker上安装mysql,docker上安装nginx

目录 一.安装docker 1.1查看Linux版本的命令这里推荐两种&#xff1a; 1.2查看内核版本有三种方式&#xff1a; 2.安装 2.1 如果之前安装了docker&#xff0c;先删除旧版本的doker 2.2 安装需要的软件包&#xff0c;yum-util提供yum-config-manager功能&#xff0c;另外两…

Android killPackageProcessesLSP 源码分析

该方法用于终止指定包名/用户ID/应用ID下符合条件的应用进程&#xff0c;涉及多进程管理、资源冻结、进程清理及优先级更新等操作。核心流程分为进程筛选、资源冻结、进程终止与资源恢复三个阶段。 /*** 从已排序的进程列表中&#xff0c;提取从指定起始索引 startIdx 开始的连…

openAICEO山姆奥特曼未来预测雄文之三个观察

《三个观察》 山姆奥特曼 这篇文章主要讲的是关于AGI&#xff08;人工通用智能&#xff09;的未来发展及其对社会的影响&#xff0c;用大白话总结如下&#xff1a; 核心观点&#xff1a; AGI是什么&#xff1f; AGI是一种能像人类一样解决各种复杂问题的智能系统&#xff0c;比…

部署yolo到k230教程

训练&#xff1a;K230 借助 AICube部署AI 视觉模型 YOLO等教程_嘉楠 ai cube多标签分类-CSDN博客K230模型训练ai cube报错生成部署文件异常_aicube部署模型显示生成部署文件异常-CSDN博客 部署&#xff1a; # 导入必要的库和模块 import os import ujson # 超快的JS…

Flask 应用封装成 Docker 服务的完整技术指南

一、实现原理 容器化核心逻辑 Docker 通过将应用代码、运行环境和依赖项打包成镜像&#xff0c;实现环境一致性。Flask 应用容器化需包含&#xff1a; Python 基础运行环境项目代码及依赖库&#xff08;requirements.txt&#xff09;WSGI服务器&#xff08;如 Gunicorn&#xf…

windows上的 Vmware Workstation 环境搭建

本文的视频版本&#xff1a;https://www.bilibili.com/video/BV1JhLRzyESh Vmware Workstation 是一款跨平台的桌面级虚拟化软件&#xff0c;可以使用 Vmware 创建虚拟机&#xff0c;我们一般使用 Linux 虚拟机&#xff08;目前主流的 Linux 发行版是 Ubuntu&#xff09;&…

Linux下终端命令行安装常见字体示例

一、准备工作&#xff1a; 准备好要安装的字体文件&#xff0c;如宋体、微软雅黑&#xff08;simsun.ttc、msyh.ttc)。进入字体路径&#xff1a; /usr/share/fonts&#xff0c;使用root权限&#xff0c;新建一个目录shell_fonts。 二、命令行安装字体&#xff1a; 将要安装…

CentOS中在线安装Docker(超详细)

1&#xff09;检查安装docker的基本要求&#xff1a; 64位CPU架构的计算机&#xff0c;目前不支持32为CPU架构的计算机 系统的Linux内核版本为3.10及以上 开启CGroups和namespace功能 2&#xff09;使用命令查看当前系统的内核版本 [rootlocalhost ~]# uname -r 3.10.0-862…

武汉昊衡科技OLI光纤微裂纹检测仪:高密度光器件的精准守护者

随着AI技术应用越来越广&#xff0c;算力需求激增&#xff0c;光通信系统正加速向小型化、高密度、多通道方向演进。硅光芯片、高速光模块等核心器件内部的光纤通道数量成倍增加&#xff0c;波导结构愈发精细&#xff0c;传统检测手段因分辨率不足、效率低下&#xff0c;难以精…

Java数据结构——Stack

Stack 栈的概念和使用栈的概念栈的使用 栈的应用出栈元素序列有效的括号栈的压入、弹出序列逆波兰表达式最小栈 栈的概念和使用 栈的概念 栈(Stack)&#xff1a;一种特殊的线性表&#xff0c;只允许再栈的一端进行插入和删除元素&#xff0c;这一端点被称为栈顶&#xff0c;另…

神经网络与计算机视觉

2016 年,随着 AlphaGo 在围棋比赛中击败李世石,“人工智能”、“神经网络”、“深度 学习”等字眼便越来越多的出现在大众眼前,智能化好像成为一种不可逆转的趋势,带给大家新奇感的同时也带来了一丝忧惧:在不远的未来,机器是否真的拥有思维和情感?《终结者》中天网大战人…

VS2019 与gitcode团队管理

1、安装git 点击下一步安装即可 2、vs2019连接gitcode 然后更改本地的代码添加文件等都可以进行远程同步操作了

Python类和对象四(十三)

魔法方法&#xff1a; 按位运算 按位于运算 只要相同才是1 或运算&#xff1a; 只要某个位是1结果就是1 、 按位非 将结果取反 按位异或&#xff1a; 左移和右移运算符&#xff1a; 右移两位 右移动n位&#xff0c;就是除以2的n次方 左移两位&#xff1a; 左移n位就是乘…

如何设置极狐GitLab 议题截止日?

极狐GitLab 是 GitLab 在中国的发行版&#xff0c;关于中文参考文档和资料有&#xff1a; 极狐GitLab 中文文档极狐GitLab 中文论坛极狐GitLab 官网 截止日期 (BASIC ALL) 可以在议题中使用截止日期&#xff0c;来跟踪截止日期并确保功能按时交付。用户至少需要报告者权限才…