写完「C语言」单链表/双向链表的建立/遍历/插入/删除 后,如何将内存中的链表信息及时的保存到文件中,又能够及时的从文件中读取出来进行处理,便需要用到”文件“的相关知识点进行文件的输入、输出。

其实,就算不懂得链表,也完全可以学习”文件“相关知识点,但在此之前最好有”指针“基础。

本篇文章整理自《C语言程序设计教程--人民邮电出版社》第十二章——文件,以作文件探讨。

一、数据流与文件概念

二、文件的打开与关闭

三、文件的顺序读写

四、文件的随机读写

五、出错检查

六、低级I/O函数与标准I/O函数

一、数据流与文件概念

1.数据流

数据的输入与输出都必须通过计算机的外围设备,不同的外围设备对于数据输入与输出的格式和方法有不同的处理方式,这就增加了编写文件访问程序的困难程度,而且很容易产生外围设备彼此不兼容的问题。数据流(Data Stream)用来解决这个问题。

数据流将整个文件内的数据看作一串连续的字符(字节),而没有记录的限制。

数据流借助文件指针的移动来访问数据,文件指针目前所指的位置即是要处理的数据,经过访问后文件指针会自动向后移动。

每个数据文件后面都有一个文件结束符号(EOF),用来告知该数据文件到此结束,若文件指针指到EOF便表示数据已访问完毕。

2.文件

“文件”是指存放在外部存储介质(可以是磁盘、光盘、磁带等)上的数据集合。操作系统对外部介质上的数据是以文件形式进行管理的。当打开一个文件或者创建一个新文件时,一个数据流和一个外部文件(可能是一个物理设备)相关联。

C语言支持的是流式文件,即前面提到的数据流,它把文件看作一个字节序列,以字节为单位进行访问,没有记录界限,即数据的输入和输出的开始和结束仅受程序控制,而不受物理符号(如回车换行符)控制。

可以从不同角度对文件进行分类

(1)根据文件依附的性质——普通文件和设备文件。

(2)根据文件的组织形式——顺序读写文件和随机读写文件。

(3)根据文件的存储形式——ASCII码文件和二进制文件。

ASCII码文件和二进制文件的主要区别:

(1)存储形式:ASCII文件将该数据类型转换为可在屏幕上显示的形式存储,二进制文件是按该数据类型在内存中的存储形式存储的。

(2)存储空间:ASCII所占空间较多,而且所占空间大小与数值大小有关。

(3)读写时间:二进制文件读写时需要转换,造成存取速度较慢。ASCII码文件则不需要。

(4)作用:ASCII码文件通常用于存放输入数据及程序的最终结果。二进制文件则不能显示出来,用于暂存程序的中间结果。

在C语言中,标准输入设备和标准输出设备是作为ASCII码文件处理的,它们分别称为标准输入文件和标准输出文件。

文件和内存的交互处理:

二、文件的打开与关闭

要打开指定的文件可使用fopen()函数

FILE *fopen(char *filename,char *mode);

其中第二个参数mode用来设定要打开的文件类型和指定文件的访问模式。

文件中的访问模式:

判断文件是否正确打开

FILE *fp;
fp=fopen("文件目录","文件中的访问模式");
if(fp==NULL)
{
printf("\n不能打开该文件!");
getch();
exit();
}

关闭文件使用fclose()

int fclose(FILE *fp);

返回值为0则表示关闭成功,若返回非0值则表示有错误发生。

由系统打开的标准设备文件,系统会自行关闭。

获取文件的属性:

获取文件描述字:int fileno(FILE *fp);

根据文件描述字获取对应文件大小:long filelength(int handle_no);

三、文件的顺序读写

顺序读写是指将文件从头到尾逐个数据读出或写入。

单字符读写函数:fgetc()和fputc():

int fgetc(FILE *fp);

功能为:读取文件指针fp目前所指文件位置中的字符,读取完毕,文件指针自动往下移一个字符位置,若文件指针已经到文件结尾,返回-1。

返回值:成功则返回读取到的字符,失败返回-1.

fgetc()函数调用中,读取的文件必须是以读或读写的方式打开的。

int fputc(char ch,FILE *fp);

功能为:把字符ch写入文件指针fp所指向文件的位置。

返回值:成功时返回字符的ASCII码,失败时返回EOF(在stdio.h中,符号常量EOF的值等于-1)。

被写入的字符可以用写、读写、追加方式打开。

字符串读写函数:fgets()和fputs():

char *fgets(char *str,int n,FILE *fp);

功能为:在文件指针fp所指文件位置读取n个字符并放入str字符数组。

返回值:如果读不到字符串时返回NULL。

int fputs(char *str,FILE *fp);

功能为:将字符串str写入文件指针fp所指文件的位置。

返回值:写入数据成功时返回非0值,写入失败时返回EOF。

格式化字符串读写函数:fscanf()和fprintf():

int fscanf(FILE *fp,"格式化字符串",【输入项地址表】);

功能为:从文件指针fp所指向的文件中按照格式字符串指定的格式将文件中的数据送到输入项地址表中。

返回值:读取数据成功返回所读取数据的个数,并将数据按照指定格式存入内存中的变量或数组中,文件指针自动向下移动。读取失败返回EOF。

int fprintf(FILE *fp,"格式化字符串",【输入项地址表】);

功能为:将输出项表中的变量值按照格式字符串制定的格式输出到文件指针fp所指向的文件位置。

返回值:成功返回输出字符数,失败则返回负值。

数据块读写函数:fread()和fwrite:

int fread(void *buffer,int size,int count,FILE *fp);

功能为:从文件指针fp所指向的文件的当前位置开始,一次读入size个字节,重复count次,并将读取到的数据存到buffer开始的内存区中,同时将读写位置指针后移size*count次。

返回值:该函数的返回值是实际读取的count值。

int fwrite(void *buffer,int size,int count,FILE *fp);

功能为:从buffer所指向的内存区开始,一次输出size个字节,重复count次,并将输出的数据放入fp所指向的文件中,同时将读写位置指针后移size*count次。

返回值:返回实际写入的数据项个数count。

四、文件的随机读写

随机读写可移动文件内部的位置指针到需要读写的位置,再进行读写,这种读写称为随机读写。实现文件的随机读写关键是要按要求移动位置指针,这成为文件的定位。

void rewind(FILE *fp);

功能为:将文件内部的位置指针移到文件的开始位置。

int fseek(FILE *fp,long offset,int whence);

功能为:文件指针由whence地址移到offset的地址。

返回值:

对应文件的指针偏移,在函数定义中并没有真正的说明清楚返回值,对于offset当为正数的时候是向文件尾偏移的,当为负数的时候是向文件头方向偏移的,这里主要是要注意偏移的大小和文件大小边界的关系。

当offset是向文件尾方向偏移的时候,无论偏移量是否超出文件尾,fseek都是返回0,当偏移量没有超出文件尾的时候,文件指针式指向正常的偏移地址的,当偏移量超出文件尾的时候,文件指针是指向文件尾的。并不会返回偏移出错-1值。

当offset是向文件头方向偏移的时候,如果offset没有超出文件头,是正常偏移,文件指针指向正确的偏移地址,fseek返回值为0.当offset超出文件头时,fseek返回出错-1值,文件指针不变还是处于原来的地址。

long ftell(FILE *_File);

功能为:得到流式文件的当前位置,用相对于文件开头的位移量来表示。由于文件中的位置指针经常移动,人们往往不容易知道其当前位置。用fell函数即可以得到当前位置。

返回值:如果返回-1L,表示出错。

int putw(int _Ch,FILE *_File);

功能为:将整数_Ch输出到fp指向的文件。

int __cdecl getw(FILE *_File);

功能为:从磁盘文件都一个整数到内存最为返回值。

五、出错检查

C语言中常用文件检测函数来检查输入/输出函数调用中的错误。

int feof(FILE *fp);

功能为:判断指针fp是否处于文件结束的位置。

返回值:如文件结束,返回值为1,否则为0。

int ferror(FILE *fp);

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

返回值:如果ferror返回值为0表示未出错,否则表示出错。

注意:对同一个文件每一次调用输入/输出函数,均产生一个新的ferror函数值,因此,应当在执行fopen函数时,ferror函数初始值自动置0。

int clearerr(FILE *fp);

功能为:本函数用于清除出错标志和文件结束标志,使它们为0值。假设在调用一个输入/输出函数时出现错误,ferror函数值为一个非0值。在调用clearerr(fp)后,ferror(fp)的值变为0。

只要出现错误标志,就会一直保留,知道对同一文件调用clearerr函数或rewind函数,或任何其他一个输入/输出函数。

六、低级I/O函数与标准I/O函数

系统输入/输出函数,或称低级I/O函数,在内存访问数据并不提供缓冲区,因此只要一有数据需要做访问操作时,便直接向磁盘作Disk I/O。此类文件函数的优点是不必占用内存空间作为缓冲区,直接向磁盘的数据文件进行读写的操作,如果不幸死机,只会影响目前正在读写的数据。其缺点就是数据访问时会造成磁盘I/O次数太过频繁而影响程序运行的速度,而且此类函数是以文件描述字来代替文件指针,且不提供格式化的处理功能。

由于现行的C版本,基本使用的都是缓冲文件系统,即标准输入/输出函数,所以,关于非缓冲文件系统的系统输入/输出函数在这里就不再详细介绍。

「C语言」文件的概念与简单数据流的读写函数的更多相关文章

  1. 「C语言」常量和变量的表示、应用和变量命名规则

    在程序运行中,其值不能改变的量成为常量. 在基本数据类型中,常量可分为整型常量.实型常量.符号常量和字符型常量(包括字符常量和字符串常量),现分别介绍如下: 目录: 一.常量 二.C语言标识符 三.变 ...

  2. 「C语言」Windows+EclipseCDT下的C语言开发环境准备

    之前写过一篇 「C语言」在Windows平台搭建C语言开发环境的多种方式 ,讨论了如何在Windows下用DEV C++.EclipseCDT.VisualStudio.Sublime Test.Cl ...

  3. 「C语言」原码反码补码与位运算

    尽管能查到各种文献,亲自归纳出自己的体系还是更能加深对该知识的理解.     本篇文章便是在结合百度百科有关原码.反码.补码和位运算的介绍并深度借鉴了张子秋和Liquor相关文章后整理而出.   目录 ...

  4. 「C语言」单链表/双向链表的建立/遍历/插入/删除

    最近临近期末的C语言课程设计比平时练习作业一下难了不止一个档次,第一次接触到了C语言的框架开发,了解了View(界面层).Service(业务逻辑层).Persistence(持久化层)的分离和耦合, ...

  5. 「C语言」int main还是void main?

    从大一入学刚接触C到现在已满7个月了,虽然刚开始就知道```int main```才是标准的写法,但一直没有深刻理解为什么不能用```void main```而必须使用```int main```. ...

  6. 「C语言」C输出hello world!系统发生了什么?

    本篇文章全部摘抄自学长博客供以后学习: http://efraim.me/2015/12/05/tech-linux-2015-12-05/ 排版因与博客园编辑器不同而稍作修改. 输出hello wo ...

  7. 「C语言」在Windows平台搭建C语言开发环境的多种方式

    新接触C语言,如何在Windows下进行C语言开发环境的搭建值得思考并整理. 以下多种开发方式择一即可(DEV C++无须环境准备). 注:本文知识来源于  Windows 平台搭建C语言集成开发环境 ...

  8. 「C语言」数据类型及混合运算与类型转换

    深入学习C语言时,有必要先了解一下数据类型的概念,以及它们之间的混合运算与类型转换. 本篇文章便是根据<C语言程序设计教程>和在线翻阅资料后整理而出.(练习题将逐步更新) 目录:     ...

  9. C语言复制文件的两种简单的方法【从根本解决问题】

    网上的方法大致有这样几种: 1.使用操作系统提供的复制文件的API 2.使用C语言本身提供的复制文件的函数 3.直接读写文件,从文件角度来操作,从而直接将一个文件复制 这里我们使用的就是这第三种. 复 ...

随机推荐

  1. Android开发中内存和UI优化

    1.内存||效率 GC这东西对于开发人员用起来比较爽,但对于技术总监或产品总监来说,他们并不在乎,在乎的是用户运行App的流畅度,待你开发完了,笑眯眯的走过来,让你测试N个适配器,烦都烦死你. 说到这 ...

  2. Linux Ubuntu搭建git服务器

    1. 安装 openssh-server ,用于创建SSH服务. sudo apt-get install openssl-server 使用命令ps -e|grep ssh,查看ssh服务是否启动. ...

  3. c++类的 static 和const那些事

    1.static成员变量(非const)必须在类外定义,在类中只是作为声明(声明其scope为该类),不能使用类初始化成员列表来初始化,只能在定义的时候初始化. 2.static const的成员变量 ...

  4. C 语言函数参数只能传指针,不能传数组

    今天被要求编写一个C/C++冒泡算法的程序,心想这还不是手到擒来的事儿,虽然最近都是用Javascript程序,很少写C/C++程序,但是好歹也用过那么多年的C语言: 首先想的是怎么让自己的代码看上去 ...

  5. 自定义组件之MoreListView

    前言 本文针对自定义组件进行一些分析.还是那句老话“授之于鱼不如授之以渔”.今天要讲的是一个自定义的可以分页的ListView. 网上都讲了些ListView分页的方法,那么为什么我在这里还需要自己写 ...

  6. VC++之自定义消息

    用户可以自定义消息,在应用程序中主动发出,这种消息一般用于应用程序的某一部分内部处理. 实例说明: 当用户按键盘上的光标上移键时,程序发送用户自定义消息,在对应的消息响应函数中弹出消息对话框,显示消息 ...

  7. ruby -- 基础学习(九)filename去除扩展名

         Rails -- filename去除扩展名 简单例子:params[:upload]['preview'].original_filename 的值为templateOne.html.er ...

  8. springboot themleaf 开发笔记

    <form id="form-query" th:action="@{/member-score/rule-save}" th:object=" ...

  9. [OpenCV] IplImage and Functions

    In this chapter, APIs will make U crazy. Good luck! Next, Review Linear Algebra.  Ref: http://blog.c ...

  10. SQL Server技术问题之触发器优缺点

    优点: 1.强化约束:强制复杂业务的规则和要求,能实现比check语句更为复杂的约束. 2.跟踪变化:触发器可以侦测数据库内的操作,从而禁止数据库中未经许可的更新和变化. 3.级联运行:侦测数据库内的 ...