C语言——文件操作

目录

1.什么是文件

1.1 程序文件和数据文件

1.2 文件名操作

1.2.1 路径分隔符

1.2.2 拼接文件路径

1.3 文件操作函数

1.4 二进制文件与文本文件 

1.4.1 文本文件

1.4.2 二进制文件 

2.文件的打开和关闭

2.1 流和标准流

2.1.1 流

2.1.2 标准流

2.1.3 使用标准流

2.2 文件指针 

2.2.1 文件指针的定义

2.2.2 文件指针的初始化

2.2.3 文件指针的读写操作 

2.2.3.1 读取文件

2.2.3.2 写入文件 

2.2.3.3 文件指针的关闭 

2.2.3.4 注意事项

2.3 文件的打开和关闭

2.3.1 文件的打开

2.3.2 文件的关闭 

2.3.3 注意事项

3.文件的顺序读写

3.1 打开文件 

3.2 顺序读取文件

3.3 顺序写入文件

3.4 关闭文件

3.5 注意事项

4.  文件的随机读写

4.1 fseek

4.2 ftell 

4.3 rewind

5.文件读取结束的判定

5.1 文件结束标志(EOF)

5.2 使用feof函数

6. 文件缓冲区 


在C语言编程中,文件操作是一项非常重要的技能。通过文件操作,我们可以实现数据的持久化存储、读取外部数据源等功能。

1.什么是文件

在C语言中,文件处理是一个强大的功能,它允许程序与持久化存储介质(如硬盘)上的文件进行交互。这种交互可以包括读取程序所需的数据、存储程序产生的结果或简单地操作和管理文件。

1.1 程序文件和数据文件

在C语言中,我们通常将源代码文件(如.c文件)称为程序文件,它们包含了程序执行的指令。当这些文件被编译器编译后,会生成可执行文件(如Windows下的.exe文件或Linux下的可执行文件)。

另一方面,数据文件是用于存储程序所需或产生的数据的文件。这些数据文件可以是文本文件,也可以是二进制文件。文本文件包含人类可读的文本数据,而二进制文件则包含程序可以直接解析的二进制数据。

1.2 文件名操作

在C语言中,文件名通常用于标识和引用文件。文件名可以包含路径信息,以便程序能够找到存储在文件系统不同位置的文件。

1.2.1 路径分隔符

在不同的操作系统中,路径分隔符可能不同。在Windows系统中,通常使用反斜杠(\)作为路径分隔符,而在UNIX和Linux系统中,则使用正斜杠(/)。在C语言中编写跨平台的代码时,最好使用\\(在字符串中使用转义字符)或/(在大多数系统中都有效)作为路径分隔符。

1.2.2 拼接文件路径

在C语言中,可以使用字符串操作函数(如strcat)来拼接文件路径和文件名。这允许程序动态地构建文件路径,以便在不同的位置查找或创建文件。

示例:拼接文件路径

1.3 文件操作函数

C语言提供了一组标准库函数来执行文件操作,包括打开文件、关闭文件、读取文件、写入文件等。以下是一些常用的文件操作函数:

  • fopen:打开文件并返回一个文件指针。
  • fclose:关闭已打开的文件。
  • fread:从文件中读取数据。
  • fwrite:将数据写入文件。
  • fgetc:从文件中读取一个字符。
  • fputc:将一个字符写入文件。
  • fgets:从文件中读取一行文本。
  • fputs:将字符串写入文件。
  • fseek:移动文件的位置指针。
  • ftell:返回文件位置指针的当前位置。

1.4 二进制文件与文本文件 

在C语言编程中,文件操作是一个重要的组成部分。根据文件内容的存储方式,我们可以将文件分为文本文件和二进制文件。

1.4.1 文本文件

文本文件是以文本形式存储数据的文件,其中数据以字符序列的形式存在。在C语言中,我们可以使用标准库函数来读取和写入文本文件。

文本文件的写入

在C语言中,我们可以使用fprintf函数或fputs函数来写入文本文件。fprintf函数允许我们按照指定的格式将数据写入文件,而fputs函数则直接将字符串写入文件。

示例代码(使用fprintf函数):

文本文件的读取

读取文本文件时,我们可以使用fscanf函数或fgets函数。fscanf函数允许我们按照指定的格式从文件中读取数据,而fgets函数则读取文件中的一行。

示例代码(使用fgets函数): 

1.4.2 二进制文件 

二进制文件是以二进制形式存储数据的文件,其中数据以字节为单位进行存储。在C语言中,我们可以使用freadfwrite函数来读写二进制文件。

二进制文件的写入

使用fwrite函数可以将数据以二进制形式写入文件。该函数需要指定要写入的数据的指针、每个数据项的大小、要写入的数据项的数量以及文件指针。

示例代码:

二进制文件的读取

读取二进制文件时,我们使用fread函数。与fwrite类似,该函数也需要指定要读取的数据的指针、每个数据项的大小、要读取的数据项的数量以及文件指针。

示例代码:

2.文件的打开和关闭

2.1 流和标准流

在C语言中,流是一个重要的概念,用于在程序内部和外部数据源(如文件、控制台等)之间传输数据。标准流则是预定义的、用于标准输入/输出操作的流。

2.1.1 流

在C语言中,流是一种抽象的数据类型,它代表了数据的源或目标。流可以是文件、控制台、网络套接字等任何可以接收或发送数据的设备或数据源。流提供了一种方便的方式来处理这些数据源,使程序员无需关心数据的具体来源或去向。

在C语言中,流是通过文件指针(FILE *)来访问的。文件指针是一个指向FILE结构体的指针,该结构体包含了流的所有状态信息(如缓冲区、文件位置等)。通过文件指针,我们可以调用各种函数来读取、写入、定位或关闭流。

2.1.2 标准流

标准流是C语言中预定义的三个流,用于标准输入/输出操作。它们分别是:

  • 标准输入流:用于从键盘或其他输入设备读取数据。在C语言中,可以使用scanfgetchar等函数从stdin读取数据。
  • 标准输出流:用于将数据输出到控制台或屏幕。在C语言中,可以使用printfputchar等函数将数据写入stdout
  • 标准错误流:用于输出错误信息或诊断信息。与stdout类似,但通常用于输出需要引起注意的重要信息。在C语言中,可以使用fprintffputs等函数将数据写入stderr

标准流是全局的,并且始终可用,无需程序员显式打开或关闭。它们是通过宏在<stdio.h>头文件中定义的,分别对应三个预定义的文件指针:stdinstdoutstderr

2.1.3 使用标准流

下面是一个简单的示例程序,演示了如何使用标准流进行输入和输出操作: 

在上面的示例中,我们首先使用printf函数将提示信息输出到标准输出流。然后,我们使用scanf函数从标准输入流读取一个整数。接下来,我们再次使用printf函数将读取到的整数输出到标准输出流。最后,如果输入的整数小于0,我们使用fprintf函数将错误信息输出到标准错误流。

2.2 文件指针 

在C语言中,文件操作是编程中常见的任务之一。为了实现对文件的读写操作,C语言提供了文件指针这一重要概念。文件指针是一个指向FILE结构体的指针,该结构体包含了文件的各种信息,如文件的位置、缓冲区等。通过文件指针,我们可以对文件进行打开、读写、关闭等操作。

2.2.1 文件指针的定义

在C语言中,文件指针通常被定义为FILE *类型。例如:

这里,fp就是一个文件指针变量,用于存储文件操作的相关信息。 

2.2.2 文件指针的初始化

文件指针在使用之前需要进行初始化,也就是要打开一个文件。C语言提供了fopen函数来打开文件,该函数返回一个FILE *类型的指针。例如:

 

在上面的代码中,fopen函数尝试以只读方式("r")打开名为"filename.txt"的文件,并将返回的文件指针赋值给fp。如果文件打开失败(如文件不存在或没有读取权限),则fopen返回NULL,此时我们应该检查fp是否为NULL并处理错误。 

2.2.3 文件指针的读写操作 

一旦文件被成功打开,我们就可以使用文件指针进行读写操作了。C语言提供了多个函数来实现这一功能,如freadfwritefscanffprintf等。

2.2.3.1 读取文件

以下是一个使用fgets函数从文件中读取一行文本的示例:

在这个例子中,fgets函数从fp指向的文件中读取一行文本,并将其存储在buffer数组中。然后,我们使用printf函数将读取到的内容输出到控制台。

2.2.3.2 写入文件 

以下是一个使用fprintf函数将数据写入文件的示例:

在这个例子中,fprintf函数将字符串"Hello, World!\n"写入到fp指向的文件中。注意,这里使用的是和printf函数类似的格式字符串。

2.2.3.3 文件指针的关闭 

在使用完文件后,我们应该使用fclose函数来关闭文件。关闭文件可以释放与文件关联的资源,并确保所有的输出都被正确地写入到文件中。例如:

在这个例子中,fclose函数关闭了由fp指向的文件。

2.2.3.4 注意事项
  1. 检查文件打开是否成功:在使用文件指针之前,一定要检查文件是否成功打开。如果文件打开失败,后续的读写操作将无法正常进行。
  2. 正确关闭文件:在使用完文件后,一定要关闭文件。不关闭文件可能会导致数据丢失或文件损坏。
  3. 注意文件路径:在打开文件时,需要提供正确的文件路径。如果路径不正确,文件将无法被打开。
  4. 注意文件读写模式:在打开文件时,需要指定正确的读写模式。不同的读写模式会影响文件的访问权限和数据的处理方式。
  5. 注意缓冲区:C语言中的文件操作通常是基于缓冲区的。这意味着在写入文件时,数据可能先被写入到缓冲区中,而不是直接写入到文件中。因此,在关闭文件之前,需要确保所有的输出都被刷新到文件中。可以使用fflush函数来刷新缓冲区。

2.3 文件的打开和关闭

在C语言中,文件的操作是编程中不可或缺的一部分。无论是读取配置文件、保存用户数据还是进行日志记录,文件操作都扮演着重要的角色。

2.3.1 文件的打开

在C语言中,文件的打开是通过fopen函数实现的。该函数接受两个参数:要打开的文件名和打开模式,并返回一个FILE *类型的指针,该指针指向一个用于后续文件操作的FILE结构体。

fopen函数原型

  • filename:要打开的文件名(包括路径,如果需要的话)。
  • mode:打开文件的模式,可以是以下值之一或它们的组合:
    • "r":只读模式。文件必须存在。
    • "w":只写模式。如果文件不存在,则创建它;如果文件存在,则清空其内容。
    • "a":追加模式。如果文件不存在,则创建它;如果文件存在,则数据将被写入到文件末尾,而不会覆盖原有内容。
    • "r+":读写模式。文件必须存在。
    • "w+":读写模式。如果文件不存在,则创建它;如果文件存在,则清空其内容。
    • "a+":读写模式。如果文件不存在,则创建它;如果文件存在,则数据将被写入到文件末尾,而不会覆盖原有内容。

示例代码

在上面的示例中,我们尝试以只读模式打开名为"example.txt"的文件。如果文件打开失败(例如文件不存在或没有读取权限),则fopen函数返回NULL,我们需要检查并处理这个错误。 

2.3.2 文件的关闭 

在完成对文件的操作后,应该使用fclose函数来关闭文件。关闭文件可以释放与文件关联的资源,并确保所有的输出都被正确地写入到文件中。

fclose函数原型

  • stream:要关闭的文件的指针。

fclose函数返回一个整数值,如果关闭成功则返回0,否则返回EOF(通常是-1)。然而,在实际编程中,我们通常只检查fclose函数是否返回了非零值,以判断关闭操作是否失败。

示例代码

在上面的示例中,我们使用fclose函数来关闭之前打开的文件。如果关闭失败,则fclose函数返回非零值,我们可以根据需要进行错误处理。 

2.3.3 注意事项

  1. 检查文件是否成功打开:在使用文件指针之前,一定要检查文件是否成功打开。如果文件打开失败,后续的读写操作将无法正常进行。
  2. 正确关闭文件:在使用完文件后,一定要关闭文件。不关闭文件可能会导致数据丢失或文件损坏,同时也可能会占用系统资源。
  3. 避免文件指针泄漏:在函数内部打开的文件,应该在函数结束前关闭。如果需要在函数之间传递文件指针,请确保正确地管理这些指针的生命周期。
  4. 处理错误:在使用文件操作时,应该始终检查函数的返回值以处理可能出现的错误。例如,如果fopen返回NULL,则表示文件打开失败;如果fclose返回非零值,则表示文件关闭失败。
  5. 文件路径:在打开文件时,需要提供正确的文件路径。如果路径不正确或文件不存在,文件将无法被打开。可以使用相对路径或绝对路径来指定文件的位置。
  6. 文件权限:在打开文件时,需要确保程序具有足够的权限来访问该文件。如果程序没有足够的权限,文件将无法被打开或写入。

 

3.文件的顺序读写

在C语言中,文件的顺序读写是文件操作的基本形式之一。顺序读写意味着数据按照它们在文件中的存储顺序进行读取或写入。

3.1 打开文件 

在进行文件的读写操作之前,首先需要打开文件。这可以通过fopen函数实现,该函数返回一个指向FILE结构体的指针,用于后续的文件操作。

在上面的示例中,我们尝试以只读模式("r")打开名为"example.txt"的文件。如果文件打开失败,fopen将返回NULL,此时我们需要进行错误处理。

3.2 顺序读取文件

使用fgets函数读取一行

fgets函数用于从文件中读取一行文本。它读取指定数量的字符(包括换行符和空字符)或读取到行尾(EOF),并将它们存储在提供的缓冲区中。

在这个示例中,我们使用fgets函数从file指向的文件中读取一行文本,并将其存储在buffer数组中。然后,我们使用printf函数将读取到的内容输出到控制台。当fgets返回NULL时,表示已经读取到文件末尾。

使用fscanf函数格式化读取

fscanf函数允许我们按照指定的格式从文件中读取数据。例如,我们可以从文件中读取整数或浮点数。

在这个示例中,我们使用fscanf函数从文件中读取整数,并将其存储在number变量中。然后,我们使用printf函数将读取到的整数输出到控制台。当fscanf的返回值不等于1时(通常是因为读取失败或已经到达文件末尾),我们停止循环。

3.3 顺序写入文件

使用fputs函数写入一行

fputs函数用于将字符串写入文件。它接受两个参数:要写入的字符串和文件指针。

在这个示例中,我们使用fputs函数将字符串"Hello, World!\n"写入到file指向的文件中。

使用fprintf函数格式化写入

fprintf函数允许我们按照指定的格式将数据写入文件。它的用法与printf函数类似,但第一个参数是文件指针。

在这个示例中,我们使用fprintf函数将整数42以字符串形式写入到file指向的文件中。

3.4 关闭文件

在完成对文件的读写操作后,应该使用fclose函数来关闭文件。这可以释放与文件关联的资源,并确保所有的输出都被正确地写入到文件中。

如果fclose函数返回非零值,则表示关闭文件时发生了错误。我们应该检查并处理这个错误。

3.5 注意事项

  1. 检查文件是否成功打开:在进行文件操作之前,一定要检查文件是否成功打开。如果文件打开失败,后续的读写操作将无法正常进行。
  2. 正确处理文件结束:在读取文件时,要注意检查是否已经到达文件末尾。可以使用feof函数来检查文件结束标志。
  3. 避免缓冲区溢出:在读取文件时,要确保提供的缓冲区足够大,以避免缓冲区溢出。可以使用fgets函数的第二个参数来指定要读取的最大字符数。
  4. 注意文件路径和权限:在打开文件时,需要提供正确的文件路径,并确保程序具有足够的权限来访问该文件。
  5. 关闭文件:在完成对文件的操作后,一定要关闭文件以释放资源。不关闭文件可能会导致数据丢失或文件损坏。

4.  文件的随机读写

4.1 fseek

fseek 函数用于设置文件的位置指针。它允许你将文件指针移动到文件的任意位置,以便从那里开始读取或写入。函数的原型如下:

  • stream:这是指向 FILE 对象的指针,表示要操作的文件。
  • offset:表示相对于 whence 的偏移量,以字节为单位。
  • whence:这是一个参数,指定从哪个位置开始计算偏移量。它可以是以下三个常量之一:
    • SEEK_SET:文件的开头。
    • SEEK_CUR:当前的位置。
    • SEEK_END:文件的末尾。

如果成功,fseek 返回0;如果失败,返回非零值。

示例

4.2 ftell 

ftell 函数返回当前文件位置指针的偏移量(相对于文件开头的字节数)。它的原型如下:

  • stream:这是指向 FILE 对象的指针,表示要操作的文件。

ftell 返回当前位置指针的偏移量,如果发生错误,则返回-1L。

示例

4.3 rewind

rewind 函数将文件位置指针重置为文件的开头。它实际上等同于 fseek(stream, 0, SEEK_SET)。函数的原型如下: 

  • stream:这是指向 FILE 对象的指针,表示要操作的文件。

示例

5.文件读取结束的判定

在C语言中,当我们从文件中读取数据时,经常需要判断是否已经读取到文件的末尾,以便正确地处理文件数据并避免越界访问。C语言提供了几种方法来检测文件读取是否结束,其中最常见的是使用文件结束标志(EOF)和feof函数。

5.1 文件结束标志(EOF)

在C语言中,文件结束标志(EOF)是一个特殊的常量,用于表示文件读取的结束。EOF通常被定义为-1,但这不是一个固定的值,而是由系统或编译器定义的。当使用文件I/O函数(如fgetcfgetsfscanf等)读取文件时,如果到达文件末尾,这些函数将返回EOF。

5.2 使用feof函数

除了直接检查文件I/O函数的返回值是否为EOF外,还可以使用feof函数来检测文件是否已经读取到末尾。feof函数接受一个文件指针作为参数,并返回一个整数值,用于指示文件是否已经到达末尾。如果文件已经到达末尾,feof将返回非零值(通常为1);否则返回零。

以下是一个使用feof函数判断文件读取结束的示例:

在上面的示例中,我们使用while (!feof(file))循环来读取文件内容,直到文件结束。在每次循环中,我们使用fgets函数从文件中读取一行数据,并检查其返回值是否为NULL。虽然fgets在到达文件末尾时会返回NULL,但直接在while循环中检查fgets的返回值可能会导致在最后一次读取时跳过数据(因为当fgets返回NULL时,循环已经终止)。因此,我们通常将feof作为循环条件,并在循环内部检查fgets的返回值。 

6. 文件缓冲区 

ANSIC标准采用“缓冲文件系统”处理的数据文件的,所谓缓冲文件系统是指系统自动地在内存中为 程序中每⼀个正在使用的文件开辟⼀块“文件缓冲区”。从内存向磁盘输出数据会先送到内存中的缓 冲区,装满缓冲区后才⼀起送到磁盘上。如果从磁盘向计算机读入数据,则从磁盘文件中读取数据输入到内存缓冲区(充满缓冲区),然后再从缓冲区逐个地将数据送到程序数据区(程序变量等)。缓 冲区的大小根据C编译系统决定的。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值