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

相关文章
|
1月前
|
存储 C语言 开发者
【C语言】字符串操作函数详解
这些字符串操作函数在C语言中提供了强大的功能,帮助开发者有效地处理字符串数据。通过对每个函数的详细讲解、示例代码和表格说明,可以更好地理解如何使用这些函数进行各种字符串操作。如果在实际编程中遇到特定的字符串处理需求,可以参考这些函数和示例,灵活运用。
66 10
|
1月前
|
存储 程序员 C语言
【C语言】文件操作函数详解
C语言提供了一组标准库函数来处理文件操作,这些函数定义在 `<stdio.h>` 头文件中。文件操作包括文件的打开、读写、关闭以及文件属性的查询等。以下是常用文件操作函数的详细讲解,包括函数原型、参数说明、返回值说明、示例代码和表格汇总。
52 9
|
1月前
|
存储 Unix Serverless
【C语言】常用函数汇总表
本文总结了C语言中常用的函数,涵盖输入/输出、字符串操作、内存管理、数学运算、时间处理、文件操作及布尔类型等多个方面。每类函数均以表格形式列出其功能和使用示例,便于快速查阅和学习。通过综合示例代码,展示了这些函数的实际应用,帮助读者更好地理解和掌握C语言的基本功能和标准库函数的使用方法。感谢阅读,希望对你有所帮助!
41 8
|
1月前
|
C语言 开发者
【C语言】数学函数详解
在C语言中,数学函数是由标准库 `math.h` 提供的。使用这些函数时,需要包含 `#include <math.h>` 头文件。以下是一些常用的数学函数的详细讲解,包括函数原型、参数说明、返回值说明以及示例代码和表格汇总。
50 6
|
1月前
|
存储 C语言
【C语言】输入/输出函数详解
在C语言中,输入/输出操作是通过标准库函数来实现的。这些函数分为两类:标准输入输出函数和文件输入输出函数。
266 6
|
1月前
|
存储 缓存 算法
【C语言】内存管理函数详细讲解
在C语言编程中,内存管理是至关重要的。动态内存分配函数允许程序在运行时请求和释放内存,这对于处理不确定大小的数据结构至关重要。以下是C语言内存管理函数的详细讲解,包括每个函数的功能、标准格式、示例代码、代码解释及其输出。
64 6
|
1月前
|
C语言 开发者
【C语言】断言函数 -《深入解析C语言调试利器 !》
断言(assert)是一种调试工具,用于在程序运行时检查某些条件是否成立。如果条件不成立,断言会触发错误,并通常会终止程序的执行。断言有助于在开发和测试阶段捕捉逻辑错误。
42 5
|
2月前
|
算法 C语言
C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项
本文深入讲解了C语言中的文件操作技巧,涵盖文件的打开与关闭、读取与写入、文件指针移动及注意事项,通过实例演示了文件操作的基本流程,帮助读者掌握这一重要技能,提升程序开发能力。
137 3
|
2月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
61 4
|
2月前
|
C语言
c语言调用的函数的声明
被调用的函数的声明: 一个函数调用另一个函数需具备的条件: 首先被调用的函数必须是已经存在的函数,即头文件中存在或已经定义过; 如果使用库函数,一般应该在本文件开头用#include命令将调用有关库函数时在所需要用到的信息“包含”到本文件中。.h文件是头文件所用的后缀。 如果使用用户自己定义的函数,而且该函数与使用它的函数在同一个文件中,一般还应该在主调函数中对被调用的函数做声明。 如果被调用的函数定义出现在主调函数之前可以不必声明。 如果已在所有函数定义之前,在函数的外部已做了函数声明,则在各个主调函数中不必多所调用的函数在做声明
41 6