C语言文件读写函数介绍【滴水逆向三期(39)笔记】

简介: C语言文件读写函数介绍【滴水逆向三期(39)笔记】

引言

在之前的学习中,我们了解了C语言指针和多级指针“骚操作”:隐藏代码到数据区(函数指针)函数指针,在学习到后面需要提取程序的PE文件结构时,我发现必须要用到C语言的文件读写函数,在这里我们来介绍一下C语言的文件读写函数。

文件分类

在学习文件读写函数之前,我们先来了解一下文件类型:在C语言中,按照数据存储的编码形式,数据文件可以分为文本文件和二进制文件两种。

文本文件

文本文件是以ASCII码值进行存储与编码的文件,其文件的内容就是字符,存储的是ASCII码的二进制,也就是我们能够直观的看得懂的,比如:‘2’,‘34’,‘5’这样,文件的数据流为字符流。

二进制文件

二进制文件是存储二进制数据的文件,存储的是数据的补码,文件的数据流为二进制流。

文件读写函数

一.关于FILE

在学习文件读写函数之前,我们先来了解一下在我们使用所有文件读写函数时,定义的结构指针FILE:

FILE是C语言为了具体实现对文件的操作而定义的一个包含文件操作相关信息的结构类型,FILE *fp定义了一个结构指针,FILE类型是用typedef重命名的,在头文件stdio.h中定义,因此,使用文件读写函数时都需要#include<stdio.h>。

下面是FILE文件类型的说明:

typedef struct{
short level;//缓冲区使用量
unsigned flags;//文件状态描述
char fd;//文件描述符
shotr bsize;//缓冲区大小
unsigned char *buffer;//文件缓冲区的首地址
unsigned char *curp;//指向文件缓冲区的首地址
unsigned char hold;//其他信息
unsigned istemp;
short token;
}FILE;

1.打开文件和关闭文件

1.打开文件

打开文件功能用于建立系统与要操作的某个文件之间的关联,指定这个文件名并请求系统分配相应的文件缓冲区内存单元。打开文件由标准函数fopen()实现,其调用方式一般为:

fopen("文件名","打开方式");

这里我们给出函数原型:

FILE *open(char *name,char *mode);

函数原型中的name即文件名,mode为打开方式。在这里我们给出C语言所有的文件打开方式:

文件打开方式
使用方式 含义 使用方式 含义
“r" 打开文本文件进行只读 ”rb" 打开二进制文件只读
“w” 新建新文本文件进行只写 “wb” 建立二进制文件进行只写
“a" 打开文本文件进行追加 “ab" 建立二进制文件进行写/追加
”r+" 打开文本文件星星读/写 “rb+” 打开二进制文件进行读/写
“w+” 建立新文本文件进行读/写 “wb+” 建立二进制文件进行读/写
“a+" 打开文本文件进行读/写/追加 ”ab+“ 打开二进制文件进行读/写/追加

值得注意的是:fopen( )函数有返回值,如果文件成功打开或建立,则返回包含文件缓冲区等信息的FILE结构指针,如果未能成功打开或建立,则返回NULL(空值)的FILE指针。

为保证文件操作的可靠性,调用fopen( )函数时最好做一个判断,以确保正常打开后再进行读写。其形式为:

if((fp=fopen("abc.txt","r"))==NULL){
  printf("File open error!\n");
  exit(0);
}

这里的exit(0)是系统标准函数,作用是关闭所有文件,并且终止程序的执行。参数0表示程序正常结束,非0参数通常表示不正常的程序结束。

这里还需要注意:文件一旦经fopen()正常打开,则对该文件的操作方式就被确定,并且直至文件关闭都不变,即若文件以r方式打开,则只能对该文件进行读操作,而不能进行写入数据操作。

一般进行文件读写操作时,常用到一下规则:

if 读文件
    指定的文件必须存在,否则出错;
if 写文件(指定的文件可以存在也可以不存在)
  if 以“w”方式写
    if 文件已存在
      源文件将被删去后重新建立;
    else
      按指定的名字创建一个新文件;
  if 以“a”方式写
    if 文件已存在
      写入的数据将被添加到指定文件原有的数据后面,不会删去原有的内容;
    else 
    按指定的名字新建一个文件(与“w”相同);
  if 文件同时读和写
    使用“r+”“w+”或“a+”打开文件;

2.关闭文件

当文件操作完成后,应及时关闭它以防止不正常的操作。

关闭文件通过调用标准函数fclose()实现,其一般格式为:

fclose(文件指针);

该函数将返回一个整数,若该数为0表示正常关闭文件,否则标志无法正常关闭文件,所以关闭文件时也应该使用条件判断:

if(fclose(fp){
  printf("Can not close the file!\n");
  exit(0);
}

关闭文件操作除了强制把缓冲区的数据写入磁盘外,还将释放文件缓冲区单元和FILE结构指针,使文件指针与具体文件脱钩。

二.文件读写

1.字符方式读写函数fgetc()和fputc()

对于文本文件,存取的数据都是ASCII码字符文本,使用这两个函数读写文件时,逐个字符地进行文件读写。

(1).fgetc()

功能:实现从fp所指示的磁盘文件读入一个字符到ch。

函数调用格式:

ch=fgetc();
(2).fputc()

功能:把一个字符ch写到fp所指示的磁盘文件上。

函数调用格式:

futc(ch,fp);

返回值:若写文件成功,则返回ch,若写文件失败,则返回EOF。

2.字符串方式文件读写函数fputs( )和pgets( )

(1).fgets( )

功能:从文本文件中读取字符串。

函数调用格式:

fgets(s,n,fp);

其中s可以是字符数组名或者字符指针,n是指定读入的字符个数,fp时文件指针。

值得注意的是:函数被调用时,最多读取n-1个字符,当函数读取的字符达到指定个数,或接收到换行符,或接收到文件结束标志EOF时,将在读取的字符后面自动添加一个‘\0’字符。若有换行符,则将换行符保留(换行符在’\0’字符之前),若有EOF,则不保留EOF。

返回值:若成功读取,则返回读取的字符串,若读取失败,则返回空指针。

(2).fputs( )

功能:向指定的文本写入一个字符串。

函数调用格式:

fputs(s,fp);

其中s为要写入的字符串,可以是字符数组名,字符型指针变量或者是字符串常量,fp是文件指针。该函数把s写入文件时,字符串结束符’\0’不会被写入文件。

返回值:若成功写入,则返回所写的最后一个字符,若写入失败,则返回EOF。

3.格式化方式文件读写函数fscanf( )和fprintf( )

(1).fscanf( )

功能:从文件中按照给定的控制格式读取数据

函数调用格式:

fscanf(fp,格式字符串,输入表);
(2).fprintf( )

功能:按照给定的控制格式向文件中写入数据

函数调用格式:

fscanf(fp,格式字符串,输出表);

4.数据块方式文件读写函数fread( )和fwrite( )

这两个函数多用于读写二进制文件。

(1).fread( )

功能:可以用来读一组数据,如一个数组元素,一个结构变量的值等。二进制文件中的数据流是非字符的,它包含的是数据在计算机内部的二进制形式。

函数调用格式:

fread(buffer,size,count,fp);

其中buffer是一个指针,在函数fread( )中,他表示存放输入数据的首地址,size表示数据块的字节数,count表示要读写的数据块数。

如:fread(fa,4,5,fp);表示从fp所指的文件中,每次读4个字节送入实数组fa中,连续读5次,即读5个实数到fa中。

返回值:成功读取到的次数

注意:size未读满时,算作读取失败

(2).fwrite( )

功能:可以用来写入一组数据,如一个数组元素,一个结构变量的值等。

函数调用格式:

fwrite(buffer,size,count,fp);

其中buffer表示存放输出数据的首地址,size表示数据块的字节数,count表示要读写的数据块数。

返回值:成功写入的次数

三.其他相关函数

1.文件定位函数

在文件读写的整个过程中,每一次成功的操作都将改变文件指针的位置,依次完成文件数据的访问与处理。

(1).重定位文件首函数rewind( )

功能:定位文件读写位置指针,使其指向读写文件的首地址,即打开文件时文件读写位置指针所指向的位置。

当访问某个文件,进行了文件读写,使指针指向了文件中间或末尾,又想回到文件的首地址重新进行读写时,可使用该函数,其调用格式为:

rewind(FILE *fp);
(2).指针移动控制函数fseek( )

功能:控制指针移动

函数调用格式:

fseek(fp,offset,form);

其中fp为文件指针,offset表示移动偏移量,它应该是long型数据,使用常量时,应加上后缀“L”,offset可为负值,form表示从哪个位置开始计算偏移量,位置可取三种:文件首部,当前位置和文件尾部,实际表示时分别对应值0、1、2,或常量SEEK_set,SEEK_CUR,SEEK_END。

(3).获取指针当前位置函数ftell( )

功能:获取当前文件读写位置,即相对于文件开头的偏移量(字节数)。

函数调用格式:

ftell(文件指针);

函数出错时返回-1L。

2.检测文件指针状态函数

(1).文件末尾检测函数feof( )

功能:判断fp指针是否已经到文件末尾,即读文件是否读到了文件结束的位置。

函数调用格式:

feof(fp);

返回值:成功返回1表示已经读到了文件末尾的位置,0表示文件未结束。

(2).读写错误检查函数ferror( )

功能:检查文件在用各种输入输出函数进行读写时是否出错。

函数调用格式:

ferror(fp);

返回值:若为出错,返回0,否则表示出错。

(3).出错标记清除函数clearerr( )

功能:清楚出错标志和文件结束标志,使他们为0值。

函数调用格式:

clearerr(fp);

文件指针必须是已经定义过的。

好了,有了这些知识,我们再加以练习,课程中的问题也就迎刃而解啦,相信大家学完后可以独立写出PE头部字段分析的程序啦,作业我会在之后上传到博客,期待大家的阅读。

关于C语言文件读写函数的介绍就到此为止,非常希望大家能够找出错误之处并提出宝贵意见,我将虚心接受!!!望我们共同进步!!!

相关文章
|
11天前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
27 6
|
1月前
|
存储 缓存 C语言
【c语言】简单的算术操作符、输入输出函数
本文介绍了C语言中的算术操作符、赋值操作符、单目操作符以及输入输出函数 `printf` 和 `scanf` 的基本用法。算术操作符包括加、减、乘、除和求余,其中除法和求余运算有特殊规则。赋值操作符用于给变量赋值,并支持复合赋值。单目操作符包括自增自减、正负号和强制类型转换。输入输出函数 `printf` 和 `scanf` 用于格式化输入和输出,支持多种占位符和格式控制。通过示例代码详细解释了这些操作符和函数的使用方法。
36 10
|
24天前
|
存储 算法 程序员
C语言:库函数
C语言的库函数是预定义的函数,用于执行常见的编程任务,如输入输出、字符串处理、数学运算等。使用库函数可以简化编程工作,提高开发效率。C标准库提供了丰富的函数,满足各种需求。
|
30天前
|
机器学习/深度学习 C语言
【c语言】一篇文章搞懂函数递归
本文详细介绍了函数递归的概念、思想及其限制条件,并通过求阶乘、打印整数每一位和求斐波那契数等实例,展示了递归的应用。递归的核心在于将大问题分解为小问题,但需注意递归可能导致效率低下和栈溢出的问题。文章最后总结了递归的优缺点,提醒读者在实际编程中合理使用递归。
60 7
|
30天前
|
存储 编译器 程序员
【c语言】函数
本文介绍了C语言中函数的基本概念,包括库函数和自定义函数的定义、使用及示例。库函数如`printf`和`scanf`,通过包含相应的头文件即可使用。自定义函数需指定返回类型、函数名、形式参数等。文中还探讨了函数的调用、形参与实参的区别、return语句的用法、函数嵌套调用、链式访问以及static关键字对变量和函数的影响,强调了static如何改变变量的生命周期和作用域,以及函数的可见性。
30 4
|
30天前
|
存储 编译器 C语言
如何在 C 语言中判断文件缓冲区是否需要刷新?
在C语言中,可以通过检查文件流的内部状态或使用`fflush`函数尝试刷新缓冲区来判断文件缓冲区是否需要刷新。通常,当缓冲区满、遇到换行符或显式调用`fflush`时,缓冲区会自动刷新。
|
30天前
|
存储 编译器 C语言
C语言:文件缓冲区刷新方式有几种
C语言中文件缓冲区的刷新方式主要包括三种:自动刷新(如遇到换行符或缓冲区满)、显式调用 fflush() 函数强制刷新、以及关闭文件时自动刷新。这些方法确保数据及时写入文件。
|
1月前
|
存储 编译器 C语言
C语言函数的定义与函数的声明的区别
C语言中,函数的定义包含函数的实现,即具体执行的代码块;而函数的声明仅描述函数的名称、返回类型和参数列表,用于告知编译器函数的存在,但不包含实现细节。声明通常放在头文件中,定义则在源文件中。
|
27天前
|
存储 C语言
【c语言】字符串函数和内存函数
本文介绍了C语言中常用的字符串函数和内存函数,包括`strlen`、`strcpy`、`strcat`、`strcmp`、`strstr`、`strncpy`、`strncat`、`strncmp`、`strtok`、`memcpy`、`memmove`和`memset`等函数的使用方法及模拟实现。文章详细讲解了每个函数的功能、参数、返回值,并提供了具体的代码示例,帮助读者更好地理解和掌握这些函数的应用。
23 0
|
27天前
|
C语言
【c语言】qsort函数及泛型冒泡排序的模拟实现
本文介绍了C语言中的`qsort`函数及其背后的回调函数概念。`qsort`函数用于对任意类型的数据进行排序,其核心在于通过函数指针调用用户自定义的比较函数。文章还详细讲解了如何实现一个泛型冒泡排序,包括比较函数、交换函数和排序函数的编写,并展示了完整的代码示例。最后,通过实际运行验证了排序的正确性,展示了泛型编程的优势。
20 0