理解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

相关文章

Go语言中泄漏缓冲区的问题解决

《Go语言中泄漏缓冲区的问题解决》缓冲区是一种常见的数据结构,常被用于在不同的并发单元之间传递数据,然而,若缓冲区使用不当,就可能引发泄漏缓冲区问题,本文就来介绍一下问题的解决,感兴趣的可以了解一下... 目录引言泄漏缓冲区的基本概念代码示例:泄漏缓冲区的产生项目场景:Web 服务器中的请求缓冲场景描述代码

Go语言如何判断两张图片的相似度

《Go语言如何判断两张图片的相似度》这篇文章主要为大家详细介绍了Go语言如何中实现判断两张图片的相似度的两种方法,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下... 在介绍技术细节前,我们先来看看图片对比在哪些场景下可以用得到:图片去重:自动删除重复图片,为存储空间"瘦身"。想象你是一个

Go语言中Recover机制的使用

《Go语言中Recover机制的使用》Go语言的recover机制通过defer函数捕获panic,实现异常恢复与程序稳定性,具有一定的参考价值,感兴趣的可以了解一下... 目录引言Recover 的基本概念基本代码示例简单的 Recover 示例嵌套函数中的 Recover项目场景中的应用Web 服务器中

Go语言中使用JWT进行身份验证的几种方式

《Go语言中使用JWT进行身份验证的几种方式》本文主要介绍了Go语言中使用JWT进行身份验证的几种方式,包括dgrijalva/jwt-go、golang-jwt/jwt、lestrrat-go/jw... 目录简介1. github.com/dgrijalva/jwt-go安装:使用示例:解释:2. gi

Go 语言中的 Struct Tag 的用法详解

《Go语言中的StructTag的用法详解》在Go语言中,结构体字段标签(StructTag)是一种用于给字段添加元信息(metadata)的机制,常用于序列化(如JSON、XML)、ORM映... 目录一、结构体标签的基本语法二、json:"token"的具体含义三、常见的标签格式变体四、使用示例五、使用

Go语言使用slices包轻松实现排序功能

《Go语言使用slices包轻松实现排序功能》在Go语言开发中,对数据进行排序是常见的需求,Go1.18版本引入的slices包提供了简洁高效的排序解决方案,支持内置类型和用户自定义类型的排序操作,本... 目录一、内置类型排序:字符串与整数的应用1. 字符串切片排序2. 整数切片排序二、检查切片排序状态:

基于Go语言实现Base62编码的三种方式以及对比分析

《基于Go语言实现Base62编码的三种方式以及对比分析》Base62编码是一种在字符编码中使用62个字符的编码方式,在计算机科学中,,Go语言是一种静态类型、编译型语言,它由Google开发并开源,... 目录一、标准库现状与解决方案1. 标准库对比表2. 解决方案完整实现代码(含边界处理)二、关键实现细

如何合理管控Java语言的异常

《如何合理管控Java语言的异常》:本文主要介绍如何合理管控Java语言的异常问题,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍2、Thorwable类3、Error4、Exception类4.1、检查异常4.2、运行时异常5、处理方式5.1. 捕获异常

C语言中的常见进制转换详解(从二进制到十六进制)

《C语言中的常见进制转换详解(从二进制到十六进制)》进制转换是计算机编程中的一个常见任务,特别是在处理低级别的数据操作时,C语言作为一门底层编程语言,在进制转换方面提供了灵活的操作方式,今天,我们将深... 目录1、进制基础2、C语言中的进制转换2.1 从十进制转换为其他进制十进制转二进制十进制转八进制十进

$在R语言中的作用示例小结

《$在R语言中的作用示例小结》在R语言中,$是一个非常重要的操作符,主要用于访问对象的成员或组件,它的用途非常广泛,不仅限于数据框(dataframe),还可以用于列表(list)、环境(enviro... 目录1. 访问数据框(data frame)中的列2. 访问列表(list)中的元素3. 访问jav