理解C语言——从小菜到大神的晋级之路(11)——文件输入输出

2023-11-23 04:38

本文主要是介绍理解C语言——从小菜到大神的晋级之路(11)——文件输入输出,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

        本节视频地址:点击这里

        在我们先前的程序中,所处理的数据或者在代码中预先指定,或者通过命令行窗口手动输入。事实上这两种方法都是效率不高的方法,相对更常用的是通过文件读写操作处理以文件形式保存的数据。C语言中的文件操作主要包括文件数据的读、写和定位等辅助操作。



1、文件



        C语言中定义了FILE这一结构用于文件操作,这一结构定义了表示文件的数据流以及用于控制文件操作的信息,如指向文件某个位置的标识、指向缓存区的指针和表示文件的状态信息等。在我们自己的源代码中定义一个FILE类型的实体通常没有意义。通常,实际操作FILE类型的实例仅在C语言提供的库函数内部完成,在编程过程中只需要定义一个FILE类型的指针变量,并对这个指针变量进行各种操作。例如我们需要输入输出两个文件,那么可以定义两个空的文件指针供后面使用:
FILE *pFin = NULL, *pFout = NULL;


2、打开文件



        对一个文件进行操作,必不可少的两个因素就是文件的完整路径和操作方式,而对文件进行操作使用的是指向文件的指针,那么一个极为关键的问题就是如何将路径和操作方式同文件指针联系起来。在C语言中,实现这一方法的途径是通过打开文件函数。打开文件函数的原型为:
FILE * fopen ( const char * filename, const char * mode );

        该函数的第一个参数传入的是目标文件的路径,第二个参数用于表示文件的操作模式,可以代表读/写、文本/二进制、刷新/续写等不同的模式。各种模式的含义有:

“r”

读文本

“rb”

读二进制

“r+”

更新读文本

“rb+”

更新读二进制

“w”

写文本

“wb”

写二进制

“w+”

更新写文本

“wb+”

更新写二进制

“a”

续写文本

“ab”

续写二进制

“a+”

更新续写文本

“ab+”

更新续二进制


        使用fopen函数打开一个文件并进行操作完成后,需要将这个文件进行关闭。关闭文件使用fclose函数完成。fclose函数原型为:

int fclose ( FILE * stream );

        该函数只有一个参数,即打开文件的指针。

        将一个文件打开、处理、最后关闭的例子如下:
int main()
{FILE *pF = NULL;fopen(“file.bin”, “rb");//文件处理fclose(pF);pF = NULL;
}


3、文本文件读写



        文件数据的读写通常有两种常用的方式,其中一种是按照文本文件的方式读写文件中的ASCII码信息,另一种方式是按照二进制文件的方式读取文件本身所表示的比特流。如果希望进行文本文件的读写操作,则在打开文件时就需要指定文件按照文本方式读取或写入。C语言为文本方式读写数据定义了多种输入输出函数:

(1)getc和putc函数


        getc和putc函数是最简单的文本读写函数,分别实现一个字符常量或变量的读取和写入操作。两个函数的声明分别如下:
int getc ( FILE * stream );
int putc ( int character, FILE * stream );

        getc函数只有一个参数就是读取目标文件的指针;putc函数第一个参数表示将要被写入目标文件的文本字符的ASCII码,第二个参数表示目标文件的指针。在putc中,字符使用int表示,但是在向文件写入的过程中,这个参数会被转化为unsigned char型进行写入。当读取文本文件到结束时,getc函数将会返回一个EOF字符,该字符的ASCII值为-1这一非法值,表示文件已结束。


(2)fgets和fputs函数


        这两个函数用于从文本文件中读取和写入字符串。声明分别如下:
char * fgets ( char * str, int num, FILE * stream );
int fputs ( const char * str, FILE * stream );

        fgets函数调用时需要三个参数,第一个参数指向字符串的首地址,第二个参数表示读入字符串的最大长度,第三个参数表示打开文件的指针。需注意,当指定第二个参数num时,这个参数所表示的长度包括了字符串结尾的0,因此可以读入的最多的字符个数为num-1。如果在读出num-1个字符之前就遇到换行符或EOF,则在这里结束读入,并在末尾补上\0。当读取成功时,函数将字符串的缓存str作为返回值返回;如果读取失败,函数将返回一个空指针。

        fputs函数用于将字符串输出到文本文件中,第一个参数表示指向字符串常量或变量的指针,第二个参数表示写入文件的指针。需注意的是,该函数写入字符串不会输出结尾的0或者换行符,如果连续调用fputs将会使多个字符串首尾相接无法分辨。因此使用时应注意手动添加'\n'等间隔符以示区分。

(3)fscanf和fprintf函数


        同scanf和printf函数类似,fscanf和fprintf函数表示格式化输入和输出数据,只是输入输出的对象由控制台界面变为文本文件。两个函数的声明如下:
int fscanf ( FILE * stream, const char * format, ... );
int fprintf ( FILE * stream, const char * format, ... );

        事实上,将两个函数的第一个参数,即指向打开文件的指针分别换成stdin和stdout,则他们的功能同scanf和printf将完全一样。因为stdin和stdout分别表示的就是代表终端键盘和终端屏幕的文件指针。
两个函数的调用方法同scanf与printf类似。


4、二进制文件读写



        对于二进制形式的文件而言无所谓格式的概念,只有按照文件原始的0/1存储方式保存着一种方法。因此读取二进制文件也不存在文本文件中各种格式、换行等因素,只有读取/写入数据和判断文件末尾两种基本情况。C语言中定义二进制文件的读写函数分别为fread和fwrite,声明方式如下:
size_t fread ( void * ptr, size_t size, size_t count, FILE * stream );
size_t fwrite ( const void * ptr, size_t size, size_t count, FILE * stream );

        fread函数定义了4个参数,第一个参数ptr为指向接受读取进来的文件数据的缓存的指针,这部分缓存必须是预先成功分配好的足够大的内存空间,如果不是合法的可写入的内存或者空间不足,在读取时程序将出现崩溃;第二个参数size表示 每一个数据单元所占字节数,这个字节通常用于表示二进制文件中数据按多少字节作为一个单元;第三个参数count表示总共读取多少个数据单元,第二三个参数的乘积size × count就是从二进制文件中读取的总的字节数;第四个参数表示打开的二进制文件指针。函数的返回值为实际读取到缓存区中数据的长度。

        fwrite函数的定义和使用方式同fread类似,只是作用是以二进制的方式向文件中写入数据。

        需要注意的是,以二进制方式读取文件时,读取的数据同文本读取时获得的ASCII码不同。二进制读取的数据的范围可以非常广,不局限于0~255之间,因此用-1代表文件结束的EOF便不再适用。在二进制文件读写中判断文件结束应使用feof函数。当函数feof(pF)返回值为1时,表示文件已经遇到文件结束,否则该函数会返回0。


5、文件定位函数



        在前面的文件读写函数中,无论读取的数据或长或短,下一次读写仍能够继续上一次结束的位置继续操作。这是由于文件结构中有“文件位置指针”这一功能。当使用fopen打开文件是,文件位置指针便指向了文件开头。每次进行读写操作,程序都会对文件位置指针处的数据进行读写。操作完成后,文件位置指针会根据读写的数据长度移动到新的位置等待下一次操作。这一切都是系统自动完成,不需要程序员进行任何干预。

        然而有时候,我们希望人为地对文件位置指针进行修改。为了实现这样的功能,C语言提供了文件定位函数,主要有fseek、ftell和rewind等。

(1)fseek函数


        fseek函数用于将文件位置指针移动到指定的位置,该函数的声明为:
int fseek ( FILE * stream, long int offset, int origin );

        该函数的第一个参数表示打开文件的指针,第二个参数表示相对于origin的偏移量(在文本文件中,该值或为0或为ftell返回的一个值),第三个参数表示文件位置指针的参考位置。不同的origin的设置代表文件相对不同位置的偏移:

Origin取值

SEEK_SET

SEEK_CUR

SEEK_END

参考位置

文件头

当前位置

文件末尾


        当文件指针pF指向一个二进制文件,则调用下面的语句使文件位置指针移动到距离文件头30字节的位置:

fseek(pF, 30L, SEEK_SET);

        调用下面的语句使文件指针移动到距离文件末尾15个int型数据长度的位置:

fseek(pF, 15L * sizeof(int), SEEK_END);

        如果文件指针指向一个文本文件,下面的语句使文件位置指针移动到文件的开头和结尾:

fseek(pF, 0L, SEEK_SET);
fseek(pF, 0L, SEEK_END);

(2)ftell函数


        该函数用于获取当前指针距离文件开头的距离,声明如下:
long int ftell ( FILE * stream );

该函数只有一个参数就是文件的指针。它的返回值代表了当前位置距离文件开始有多少个字节。


(3)rewind函数


        该函数的作用在于将文件位置指针重置与文件开头,声明如下:
void rewind ( FILE * stream );

        该函数只有一个参数即文件指针,没有返回值。它的作用同下面fseek的用法类似:

fseek(pF, 0L, SEEK_SET);


这篇关于理解C语言——从小菜到大神的晋级之路(11)——文件输入输出的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



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

相关文章

C语言逗号运算符和逗号表达式的使用小结

《C语言逗号运算符和逗号表达式的使用小结》本文详细介绍了C语言中的逗号运算符和逗号表达式,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习... 在C语言中逗号“,”也是一种运算符,称为逗号运算符。 其功能是把两个表达式连接其一般形式为:表达

Go语言实现桥接模式

《Go语言实现桥接模式》桥接模式是一种结构型设计模式,它将抽象部分与实现部分分离,使它们可以独立地变化,本文就来介绍一下了Go语言实现桥接模式,感兴趣的可以了解一下... 目录简介核心概念为什么使用桥接模式?应用场景案例分析步骤一:定义实现接口步骤二:创建具体实现类步骤三:定义抽象类步骤四:创建扩展抽象类步

GO语言实现串口简单通讯

《GO语言实现串口简单通讯》本文分享了使用Go语言进行串口通讯的实践过程,详细介绍了串口配置、数据发送与接收的代码实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要... 目录背景串口通讯代码代码块分解解析完整代码运行结果背景最近再学习 go 语言,在某宝用5块钱买了个

GO语言zap日志库理解和使用方法示例

《GO语言zap日志库理解和使用方法示例》Zap是一个高性能、结构化日志库,专为Go语言设计,它由Uber开源,并且在Go社区中非常受欢迎,:本文主要介绍GO语言zap日志库理解和使用方法的相关资... 目录1. zap日志库介绍2.安装zap库3.配置日志记录器3.1 Logger3.2 Sugared

Go语言中如何进行数据库查询操作

《Go语言中如何进行数据库查询操作》在Go语言中,与数据库交互通常通过使用数据库驱动来实现,Go语言支持多种数据库,如MySQL、PostgreSQL、SQLite等,每种数据库都有其对应的官方或第三... 查询函数QueryRow和Query详细对比特性QueryRowQuery返回值数量1个:*sql

深入理解Redis线程模型的原理及使用

《深入理解Redis线程模型的原理及使用》Redis的线程模型整体还是多线程的,只是后台执行指令的核心线程是单线程的,整个线程模型可以理解为还是以单线程为主,基于这种单线程为主的线程模型,不同客户端的... 目录1 Redis是单线程www.chinasem.cn还是多线程2 Redis如何保证指令原子性2.

深入理解MySQL流模式

《深入理解MySQL流模式》MySQL的Binlog流模式是一种实时读取二进制日志的技术,允许下游系统几乎无延迟地获取数据库变更事件,适用于需要极低延迟复制的场景,感兴趣的可以了解一下... 目录核心概念一句话总结1. 背景知识:什么是 Binlog?2. 传统方式 vs. 流模式传统文件方式 (非流式)流

深入理解Go之==的使用

《深入理解Go之==的使用》本文主要介绍了深入理解Go之==的使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录概述类型基本类型复合类型引用类型接口类型使用type定义的类型不可比较性谈谈map总结概述相信==判等操作,大

GO语言中gox交叉编译的实现

《GO语言中gox交叉编译的实现》本文主要介绍了GO语言中gox交叉编译的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧... 目录一、安装二、使用三、遇到的问题1、开启CGO2、修改环境变量最近在工作中使用GO语言进行编码开发,因

从基础到高级详解Go语言中错误处理的实践指南

《从基础到高级详解Go语言中错误处理的实践指南》Go语言采用了一种独特而明确的错误处理哲学,与其他主流编程语言形成鲜明对比,本文将为大家详细介绍Go语言中错误处理详细方法,希望对大家有所帮助... 目录1 Go 错误处理哲学与核心机制1.1 错误接口设计1.2 错误与异常的区别2 错误创建与检查2.1 基础