【C语言】文件操作(中卷)

2024-06-03 05:28
文章标签 语言 操作 中卷

本文主要是介绍【C语言】文件操作(中卷),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

前言

在文件操作(上卷)中,讲到的主要都是正式文件操作开始之前的前置知识,而这一卷中,我们将开始正式地操作文件。

在上卷中我们已经说到,stdin stdout stderr是三个C语言程序启动时默认打开的流。这三个流的类型是:FILE*,通常称为文件指针。而C语言,就是通过FILE*的文件指针来维护流的各种操作的。

文件指针

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

每个被使用的文件(包括外部设备)都在内存中开辟了一个相应的文件信息区,用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。当我们打开一个文件时,就会创造一个和这个文件相关的文件信息区。

这些信息保存在一个结构体变量中。该结构体类型是由系统声明的,取名FILE

比如图中,我们现在有一个data.txt文件,操作这个文件就会创造一个FILE类型的文件信息区f,文件信息区和我们的文件建立了一定联系,里面放着文件相关的各种信息。

在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;//使用typedef重命名

可以看到我们的FILE其实是对一个结构体类型的重命名,FILE就是这样一个结构体类型。

所以我们创建的文件信息区就是创建的一个结构体变量。

注意,不同的C编译器的FILE类型包含的内容不完全相同,但大同小异。

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

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

我们的文件信息区是有地址的,我们将其地址放到一个类型为FILE*的指针中去。

我们上面说stdin stdout stderr这三个流的类型是:FILE*,现在我们知道,其实它们就是指向FILE类型文件信息区的三个指针。

每个文件都有自己的文件信息区,文件是在硬盘上放着的,文件信息区是在内存上放着的。

文件的打开和关闭

文件的操作:

1.打开文件---打开流

2.读写文件---读/写流

3.关闭文件---关闭流

 流的底层是怎么做的,不用关心。

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

fopen

 第一个参数是文件名,后一个参数是文件的打开方式。

最终返回的是文件信息的地址。用它可以找到文件信息区,就可以找到流。

mode表示文件的打开模式,有很多种,以下都是:

注意是双引号。

文件操作示意图:

 "w"(只读),如果指定的文件存在,会把文件内容清洗掉,然后展示出一个空的文件;如果指定的文件不存在,就会建立一个新的文件。

演示:

 

可以看到,我们就生成了一个data.txt,大小为0。

 现在我们在data.txt里写一点东西:

那么当我们再次运行程序,此时是已存在这个文件,会发现运行完再打开这个文件发现已经被改为空白了:

这就是"w"(只读)的特点,如果指定的文件存在,会把文件内容清洗掉,然后展示出一个空的文件;如果指定的文件不存在,就会建立一个新的文件。

如果是"r"的方式打开,现在我们还是打开data.txt,因为存在,所以运行起来不会报错。

如果我们把这个文件删除然后再运行:

这时就给出了相应的报错信息:没有这样的文件或目录。

打开文件后我们读文件或写文件,然后我们就要关闭文件

fclose

 所以我们就这样关闭文件:

但是流关掉后,我们的pf的地址其实还在,不会自己置空,避免变为野指针,我们要置为空:

打开其他位置的文件

可以发现,我们现在打开的文件必须在当前工程路径底下,那如果现在我们想打开桌面放置的一个文件呢?

那就加上路径。路径在哪看?右击这个文件点开属性:

可以看到位置一行,后面的就是路径,所以我们这样写:

 

记得将\写为\\,否则会被当做转义字符。 

这种从“根”上开始的写法叫做绝对路径

此外,还有一种相对路径的写法:

比如,我们可以用来打开上一级路径下的文件:

这是我们的工程目录:

(可以理解为test.c所在的这一个目录) 

所以这就是上一级路径:

.表示当前路径,..表示上一级路径,所以我们的代码这样写:

FILE* pf = fopen(".\\..\\data.txt", "w");

这就是,当前路径的上一级路径底下的data.txt文件。

如果我们想要打开上一级的上一级路径下的文件,就这样写:

FILE* pf = fopen(".\\..\\..\\data.txt", "w");

这就是,当前路径的上一级的上一级路径底下的data.txt文件。

从这种写法可以看出,相对路径所谓的相对,就是相对于当前位置的路径的意思。

文件的顺序读写

有两种读写,一种叫顺序读写,一种叫随机读写。

顺序读写函数介绍

 fgetc也就是读字符。fputc是写字符。fgets是读字符串,fputs是写字符串。

文本行就是多个字符的意思。

fscanf和fprintf是格式化输入和输出。

fread和fwrite是二进制输入和输出。

前面的6个函数读和写的都是文本信息(也就是肉眼能看得懂),而后面两个读和写的是二进制的信息。

fputc函数

前一个参数是要写的字符,后一个参数是流 。

现在我们可以把字母a~z写到test.txt中去。

 fgetc函数

只有一个参数,就是流(文件指针),返回一个int。

成功情况返回的是读到字符的ASCII码值。 

如果读取失败,会返回一个EOF。也就是end of file,文件的结束标志,其实设置在全局变量中。 可以写下EOF右击转到定义,会看到其实本质就是-1

那么现在我们可以试着读一下我们刚才写的字符:

其实在我们读或者写的时候,文件都有一个光标在按顺序移动,否则读和写就乱套了。 

 我们还可以这样写,把所有字符都读取:

补充:fgetc fputc的适用范围

这时我们还注意到,上面说到,前6个函数适用于所有输入输出流 ,这是个什么情况呢?

当我们以读的形式打开文件,得到的是文件的输入流;当我们以写的形式打开文件,得到的是文件的输出流。

stdin stdout也是输入和输出流,那么我们前面提到的两个函数也能适用于这两个标准流。

 所以这两个函数可以适用于标准输出输入流或文件输出输入流。

到此,本文内容就结束了,后面会继续补充文件操作相关的内容,祝阅读愉快^_^

这篇关于【C语言】文件操作(中卷)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1026116

相关文章

科研绘图系列:R语言扩展物种堆积图(Extended Stacked Barplot)

介绍 R语言的扩展物种堆积图是一种数据可视化工具,它不仅展示了物种的堆积结果,还整合了不同样本分组之间的差异性分析结果。这种图形表示方法能够直观地比较不同物种在各个分组中的显著性差异,为研究者提供了一种有效的数据解读方式。 加载R包 knitr::opts_chunk$set(warning = F, message = F)library(tidyverse)library(phyl

透彻!驯服大型语言模型(LLMs)的五种方法,及具体方法选择思路

引言 随着时间的发展,大型语言模型不再停留在演示阶段而是逐步面向生产系统的应用,随着人们期望的不断增加,目标也发生了巨大的变化。在短短的几个月的时间里,人们对大模型的认识已经从对其zero-shot能力感到惊讶,转变为考虑改进模型质量、提高模型可用性。 「大语言模型(LLMs)其实就是利用高容量的模型架构(例如Transformer)对海量的、多种多样的数据分布进行建模得到,它包含了大量的先验

C语言 | Leetcode C语言题解之第393题UTF-8编码验证

题目: 题解: static const int MASK1 = 1 << 7;static const int MASK2 = (1 << 7) + (1 << 6);bool isValid(int num) {return (num & MASK2) == MASK1;}int getBytes(int num) {if ((num & MASK1) == 0) {return

MiniGPT-3D, 首个高效的3D点云大语言模型,仅需一张RTX3090显卡,训练一天时间,已开源

项目主页:https://tangyuan96.github.io/minigpt_3d_project_page/ 代码:https://github.com/TangYuan96/MiniGPT-3D 论文:https://arxiv.org/pdf/2405.01413 MiniGPT-3D在多个任务上取得了SoTA,被ACM MM2024接收,只拥有47.8M的可训练参数,在一张RTX

如何确定 Go 语言中 HTTP 连接池的最佳参数?

确定 Go 语言中 HTTP 连接池的最佳参数可以通过以下几种方式: 一、分析应用场景和需求 并发请求量: 确定应用程序在特定时间段内可能同时发起的 HTTP 请求数量。如果并发请求量很高,需要设置较大的连接池参数以满足需求。例如,对于一个高并发的 Web 服务,可能同时有数百个请求在处理,此时需要较大的连接池大小。可以通过压力测试工具模拟高并发场景,观察系统在不同并发请求下的性能表现,从而

C语言:柔性数组

数组定义 柔性数组 err int arr[0] = {0}; // ERROR 柔性数组 // 常见struct Test{int len;char arr[1024];} // 柔性数组struct Test{int len;char arr[0];}struct Test *t;t = malloc(sizeof(Test) + 11);strcpy(t->arr,

C语言指针入门 《C语言非常道》

C语言指针入门 《C语言非常道》 作为一个程序员,我接触 C 语言有十年了。有的朋友让我推荐 C 语言的参考书,我不敢乱推荐,尤其是国内作者写的书,往往七拼八凑,漏洞百出。 但是,李忠老师的《C语言非常道》值得一读。对了,李老师有个官网,网址是: 李忠老师官网 最棒的是,有配套的教学视频,可以试看。 试看点这里 接下来言归正传,讲解指针。以下内容很多都参考了李忠老师的《C语言非

C 语言基础之数组

文章目录 什么是数组数组变量的声明多维数组 什么是数组 数组,顾名思义,就是一组数。 假如班上有 30 个同学,让你编程统计每个人的分数,求最高分、最低分、平均分等。如果不知道数组,你只能这样写代码: int ZhangSan_score = 95;int LiSi_score = 90;......int LiuDong_score = 100;int Zhou

C 语言的基本数据类型

C 语言的基本数据类型 注:本文面向 C 语言初学者,如果你是熟手,那就不用看了。 有人问我,char、short、int、long、float、double 等这些关键字到底是什么意思,如果说他们是数据类型的话,那么为啥有这么多数据类型呢? 如果写了一句: int a; 那么执行的时候在内存中会有什么变化呢? 橡皮泥大家都玩过吧,一般你买橡皮泥的时候,店家会赠送一些模板。 上

动手学深度学习【数据操作+数据预处理】

import osos.makedirs(os.path.join('.', 'data'), exist_ok=True)data_file = os.path.join('.', 'data', 'house_tiny.csv')with open(data_file, 'w') as f:f.write('NumRooms,Alley,Price\n') # 列名f.write('NA