文件操作详解

一.什么是文件

 文件是用于存储和组织数据的一种数据存储单元。是存储数据的地方。在程序设计中,文件因其功能分为两种,程序文件和数据文件。

二.为什么要使用文件

我们先把变量b初始化为0,运行代🐎后,从键盘上输入二十,这是b就会变为20.但当我们退出程序,重新运行后,b又变回了0.20这个数据就丢失了,所以如果想将数据进行长久化的保存,就要使用文件了。

三.文件分类

3.1 程序文件

程序文件包括源程序文件(后缀为.c),目标文件(windows环境后缀为.obj),可执行程序(windows 环境后缀为.exe)

3.2 数据文件

数据文件中存储程序运行时读取的数据。在以前所处理数据的输入输出都是以终端为对象的,即从终端的键盘输入数据,运行结果显示到显示器上。其实有时候我们会把信息输出到磁盘上,当需要的时候再从磁盘上把数据读取到内存中使用,这里处理的就是磁盘上文件。

3.3 文件名(文件标识)

文件名可以帮助我们快速的找到目标文件。文件名包括三部分:文件路径+文件名主干+文件后缀

c:\code\test.txt

四.数据文件

根据数据组织形式的不同,数据文件被称为文本文件或者二进制文件。如果数据在内存中以二进制形式存储,且不加转换的输出到外存,那就是二进制文件。如果要求在外存上以ASCII码的形式存储,则需要在存储前转换。以ASCII字符的形式存储的文件就是文本文件。

那么一个数据在内存中是如何存储的呢?

字符型在内存中以ASCLL的形式存储,数值型数据既可以用ASCLL值形式存储,也可以用二进制形式存储。

例如有一个整数10000.如果以ASCLL的形式输出到磁盘(外存),那麽他将占用五个字节的空间大小(每个字符一个字节),但如果以二进制形式输出到磁盘,只占用4个字节大小的空间(整形占用4个字节)

1的ASCLL值是49,0的是48

五.文件的打开和关闭

5.1 流

我们程序的数据需要输出到各种外部设备,也需要从外部设备获取数据,不同的外部设备的输入输出 操作各不相同,为了方便程序员对各种设备进行方便的操作,我们抽象出了流的概念,我们可以把流 想象成流淌着字符的河。 C程序针对文件、画面、键盘等的数据输⼊输出操作都是通过流操作的。 ⼀般情况下,我们要想向流里写数据,或者从流中读取数据,都是要打开流,然后操作。

5.1.2标准流

那为什么我们从键盘输⼊数据,向屏幕上输出数据,并没有打开流呢? 那是因为C语言程序在启动的时候,默认打开了3个流: •1.stdin - 标准输入流,在大多数的环境中从键盘输⼊,scanf函数就是从标准输入流中读取数据。 • 2.stdout - 标准输出流,大多数的环境中输出至显示器界面,printf函数就是将信息输出到标准输出 流中。 •3. sterr标准错误流-,大多数环境中输出到显示器界面。 这是默认打开了这三个流,我们使⽤scanf、printf等函数就可以直接进行输入输出操作的。 stdin、stdout、stderr 三个流的类型是: FILE* ,通常称为文件指针,c语言中,就是通过 FILE* 的文件指针来维护流的各种操作的。

5.2 文件指针

为什么要有文件指针这个东西呢?原因是每个文件在使用时都在内存中开辟了一个文件信息区。用来存放文件的相关信息(如文件的名字,文件状态及文件当前的位置等)。这些信息是保存在⼀个结构体变量中的。该结构体类型是由系统声明的,取名FILE。

每当打开⼀个文件的时候,系统会根据文件的情况自动创建⼀个FILE结构的变量,并填充其中的信 息,我们不用关注其中的细节。 一般都是通过⼀个FILE的指针来维护这个FILE结构的变量,这样使用起来更加方便。

FILE* pf;

pf是一个类型为FILE的指针变量,pf指向某个文件的的信息区。。通过该文件信息区中的信息就能够访问该文件。也就是说,通过文件指针变量能够间接找到与它关联的文件

5.3 文件的使用

如何把一只大象从冰箱里解救出来?第一步打开冰箱,第二部放出大象,第三部关闭冰箱门。使用文件也是一样道理。第一部我们需要打开文件,第二步读/写文件,第三步关闭文件。

5.3.1 打开文件

打开文件使用的是fopen函数

但打开文件也有可能失败,失败时将返回空指针,所以需要检验返回的是否为空指针,完整代码如下,如果为空指针,perror就会报错,程序终止。

再来解释文件名和打开模式。

5.3.1.1文件名

这个文件名分为相对路径与绝对路径。首先来说相对路径"data.txt"就是相对路径,是自动在该文件夹下建立的一个文件,程序运行后,在程序路径下新建。

那么我们如果想在该程序路径下的前一个路径建立该怎末办呢?先给出结论。

1. 是在相对路径前加一个加 ./  便可以当前目录建立文件 (或者什么都不加也是当前路径)

2.  ../  表示上一级路径

程序运行后便可在上一级路径创建一个data.txt。

再次加一个../就再向前一个路径

然后就是绝对路径了,就是该文件的完整地址。如

但是我们在程序中不应该这样写,防止/代表转义字符。写法应该再加一个/。如下

5.3.1.2 打开模式

文件名解释完了,就该解释"w"是什么意思了。

实际上,文件有许多种不同的打开方式。

在说打开模式之前,先说程序中读和写(输入与输出的区别)

1.只读 "r"

含义:为了输入数据,打开一个已经存在的文本文件,如果指定文件不存在,则程序报错。读不影响文件内已经存在的数据

2.只写 "w"

含义:为了输出数据,打开一个文本文件,若文件不存在,则建立一个新的文件,注意,使用w会使文件中内容被删除

3.追加"a"

含义:向文本文件末尾添加数据,若文件不存在,测建立一个新的文件。

4.只读"rb"

含义:为了输入数据,打开一个二进制文件,不存在与r相同

5.只写"rw"

含义:为了输出数据,打开一个二进制文件,若文件不存在,则建立一个新的文件,注意,使用w会使文件中内容被删除

6.其余

5.3.2 读写文件

读写文件可以一个一个按照顺序读写,也可以跳着位置读写,也就是分为顺序读写与随机读写。

5.3.2.1 顺序读写

1.顺序读写函数介绍

2.函数介绍

一、fgetc

我们先在文件data.txt中储存abcd

在运行程序,得到了,abc,其实读取文件时文件的内部存在光标,读取一个字符就往后移到一位,也就是顺序读了。

那么如何从键盘上读取内容呢?

只需把文件指针pf改为标准输入流stdin即可!

二、fputc

将数据输出到文件中,如下实现

那么如河将代码输出到屏幕上呢?

这个时候我们就可以用标准输出流stdout了

如今我们已经学完了fgetc与gputc函数了,那么如何将一份文件里的内容拷贝到另一份文件之中呢?

这就要用到fgetc若读取失败返回EOF的机制了,我们可以玄幻读写,判断条件就是返回值是否是EOF,代码实现如下。

int main()
{
    //先把26字母输出到一个文件A中,再将文件A中的内容(字母表)拷贝到文件B中
    FILE* pa = fopen("dataA.txt", "w");
    FILE* pb = fopen("dataB.txt", "w");
    if (pa == NULL)
    {
        perror("fopenA");
        return 1;
    }if (pb == NULL)
    {
        perror("fopen");
        return 1;
    }

    //输出字母表到文件A中
    for (int i = 0; i < 26; i++)
    {
        fputc('a' + i, pa);
    }
    //拷贝
    int ch = 0;
    while ((ch=fgetc(pa))!=EOF)
    {
        fputc(ch, pb);
    }
    fclose(pa);
    fclose(pb);
    pa = NULL;
    pb = NULL;
}

三、fputs

名字见作文本读取函数,相信大家已经发现与fputc的不同了。一个后缀是c一个是s,s--字符串,c--字符,所以是字符输出函数

我们可以把字符串写到文件里

当然这里直接写fputs("abcdef",pf);也是可以的.

也可以写到屏幕上

四、fgets

这个函数是把流里的数据读入到程序中

读取A里的字符到字符数组ch里

可以看到,只读入了10-1个字符,最后读入了/0

五、fscanf函数--格式化输入函数

首先,这个格式化就是结构体。我们来学习一下scanf与fscanf的区别

比如说我们要把文件中的数据储存到结构体中

六、fprintf 函数

比如把小于同志的信息也写到文件中

七、fwrite 函数

将数据以二进制形式写到文件中(只能文件流)

比如说我们把一些数据以二进制的形式写到文件中,代码如下可以看到,文件中储存了一些我们看不懂的的(记事本是文本阅读器,看不懂二进制数据的)

但是我们看不懂,有人可以帮我们看啊--fread函数

八、fread函数

那我们可以把刚刚放在uuu.2中的二进制数据读出来啊,代码实现如下

上⾯说的适用于所有输入流⼀般指适⽤于标准输入流和其他输入流(如文件输入流);所有输出流一般适用于标准输出流和其他输出流(如文件输出流)。

5.3.2.2 文件的随机读写

随机读写实际上都是对光标位置的不同偏移

--fseek函数--根据文件指针的位置和偏移量来定位文件指针(文件内容的光标)

那我们如何知道当前位置的偏移量呢?

--ftell函数--返回相对于起始位置的偏移量

也可以用来算一下文件的大小,先用sfeek从末尾开始偏移0,再用ftell返回

---rewind--让文件的光标返回起始位置

5.3.3 文件读取结束的判定

当我们在读取文件时,如何判定文件是否正常的读取结束呢(遇见文件末尾)?

feof--判定文件读取结束后,判断是否是因为遇见文件末尾而结束

ferror--判定文件读取结束后,判断是否是因为遇到错误而结束

1.文本文件读取是否结束,判断返回值是否为 EOF ( fgetc ),或者 NULL ( fgets ) 例如: fgetc 判断是否为 EOF . • fgets 判断返回值是否为 NULL

5.3.4 关闭文件

函数fclose就是用来关闭文件的,直接用 fclose(文件指针) 即可关闭文件。关闭文件后,指针pf就程了野指针,所以最后一步我们需要把指针设为空指针即为 pf = NULL;

fclose(pf);
pf=NULL;

六、文件相关知识

1.c语言源程序是文本文件,目标文件和可执行文件是二进制文件。(T)

2.二进制文件名不能用.txt作为扩展名,否则二进制文件读写函数fread和fwrite将出错。(F)

在 C 语言中,freadfwrite 函数用于读写二进制文件,它们并不关心文件的扩展名,而是关心文件是否以二进制模式打开。

在 Windows 系统上,文本文件和二进制文件的区别通常是由文件的打开模式决定的。如果你以文本模式打开一个文件,换行符可能会被转换(例如,在 Windows 上,\n 会被转换为 \r\n)。相反,如果你以二进制模式打开文件,所有的字节都会保持原样,不会有任何转换。

下面是一些常见的文件打开模式:

  • "r":以只读方式打开文本文件。
  • "rb":以只读方式打开二进制文件。
  • "w":以写入方式打开文本文件,如果文件存在,其内容会被截断为零长度。
  • "wb":以写入方式打开二进制文件,如果文件存在,其内容会被截断为零长度。

因此,如果你使用 "rb""wb" 模式打开文件,即使文件的扩展名是 .txtfreadfwrite 也不会出错,因为它们以二进制方式操作文件。

3.一般不能用任何一个文本编辑器打开二进制文件进行阅读。(T)

4.文件指针和位置指针都是随着文件的读写操作在不断改变。(F)

5.C系统的标准输出文件stdout是指显示器。(T)

6.缓冲文件系统的文件缓冲区位于(内存数据区中)。

7.文件由数据流形式组成,可按数据的存放形式分为二进制文件和文本文件(T)

8.打开一个已存在文件并进行了写操作后,原有文件中的全部数据必定被覆盖。(F)

这个叙述是错误的。默认情况下,打开一个已存在的文件进行写操作(如使用 "w" 模式),会截断文件,即删除文件中的现有内容。但如果使用 "a"(追加)模式,写操作会在文件末尾添加数据,而不会覆盖现有内容。.

9.在一个程序中当对文件进行了写操作后,必须先关闭该文件然后再打开,才能读到第一个数据。

这个叙述是错误的。在对文件进行写操作后,可以使用 fseek 或 rewind 函数将文件位置指针重新定位到文件的开始,而无需关闭并重新打开文件。

10.当对文件的读(写)操作完成之后,必须将它关闭,否则可能导致数据丢失。(T)

这个叙述是正确的。当文件的读写操作完成后,应当关闭文件。不关闭文件可能导致数据缓冲区中的数据未能正确地刷新到磁盘上,从而导致数据丢失或文件损坏。

11.a+" 模式具有以下特性:

如果文件存在,它会被打开以供读写,文件指针会位于文件末尾。这意味着任何写操作都会追加到现有内容之后。

如果文件不存在,新文件将被创建,并且文件指针会位于文件的开始,准备好进行写操作。

12.按数据的组织形式划分,文件可以分为文本文件和二进制文件.  按存储介质划分,文件可以分为:  普通文件和设备文件

13.若读文件还未读到文件末尾, feof()函数的返回值是( 0)。

14.若fp是指向某文件的指针,且已读到文件末尾,则表达式feof(fp)的返回值是( 非零值)

byebye.

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值