首页 > 编程笔记 > C语言笔记 阅读:148

C语言fopen()函数的用法(附带实例)

在 C语言中,fopen() 是一个用于打开文件的库函数,该函数在<stdio.h>头文件中。

fopen() 函数可以用来创建新文件或打开现有文件,并返回一个 FILE 指针,该指针用于在后续的文件 I/O 操作中引用该文件。

fopen() 函数的语法格式如下:
FILE *fopen (const char * filename, const char * mode);
参数说明:
下表罗列了文件的打开模式:

控制读写权限的字符串(必须指明)
打开方式 说明
"r" 以“只读”方式打开文件。只允许读取,不允许写入。文件必须存在,否则打开失败。
"w" 以“写入”方式打开文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容(相当于删除原文件,再创建一个新文件)。
"a" 以“追加”方式打开文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件的末尾(文件原有的内容保留)。
"r+" 以“读写”方式打开文件。既可以读取也可以写入,也就是随意更新文件。文件必须存在,否则打开失败。
"w+" 以“写入/更新”方式打开文件,相当于wr+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么清空文件内容(相当于删除原文件,再创建一个新文件)。
"a+" 以“追加/更新”方式打开文件,相当于a和r+叠加的效果。既可以读取也可以写入,也就是随意更新文件。如果文件不存在,那么创建一个新文件;如果文件存在,那么将写入的数据追加到文件的末尾(文件原有的内容保留)。
控制读写方式的字符串(可以不写)
打开方式 说明
"t" 文本文件。如果不写,默认为"t"
"b" 二进制文件。

返回值:
例如,我们可以使用相对路径 data.txt,在当前项目的目录下创建一个名为 data.txt 的文件。当然,也可以在 Windows 上使用形如 F:/projects/data.txt 的绝对路径,这意味着将在 F 盘的 projects 文件夹中创建 data.txt 文件。
#include <stdio.h>
int main()
{
    // 创建一个名为 data.txt 的文件
    FILE *pFile = fopen("data.txt", "w");
    if (pFile == NULL)
    {
        // 文件创建失败
        return -1;
    }
    // 文件创建成功
    return 0;
}
函数 fopen() 的第一个参数为字符串,内容为需要操作的文件路径,第二个参数也为字符串,内容为文件的操作模式。程序运行后,我们即可在项目目录中看到 data.txt 文件。当然,我们没有写入任何内容,因此这个文件是一个空文件。

注意,读者在运行程序时可能会遇到报一个 error C4996 错误,提示我们 fopen() 是一个不安全的函数。想知道解决方案的读者可以阅读《VS安全函数问题(C语言安全函数)》一节。

文本模式与二进制模式

在 C语言中,文件可以以文本模式(text mode)或二进制模式(binary mode)打开。两种模式主要在数据读写方式和行尾符处理上有所区别。

1) 文本模式

文本模式主要用于处理文本文件,如纯文本文件、源代码文件等。

在文本模式下,文件中的数据按照字符序列进行处理。当读写文件时,C 语言会自动处理行尾符。在不同的操作系统中,行尾符的表示方式可能不同。

查看下图,我们使用十六进制查看器,打开之前创建好的 data.txt 文件(提前写入了"123\n"和"3.1415\n"),仔细研究这个文件的组成(这里使用的是 Visual Studio Code,如果没有查看器也没关系,理解内容即可)。


图 1 Windows系统中的文件组成

很明显,这个文件中记录了写入字符的 ASCII 码。例如:字符 '1' 的 ASCII 码为十六进制 31。字符 '2' 的 ASCII 码为十六进制的 32。字符 '3' 的 ASCII 码为十六进制的 33。

按照逻辑,字符 '3' 后面应当为换行符'\n'。但是在文件中,第一行末尾可见字符 '3' 与第二行开头可见字符 '3' 之间居然有两个字符。

这两个字符的 ASCII 码为十六进制的 0D 和 0A。我们只要查一查 ASCII 表就会发现,十六进制的 0A 是我们熟悉的换行,转义序列为 '\n'。十六进制的 0D 的意义为回车,转义序列为 '\r'。

为什么会出现回车和换行两个字符呢?

这是历史原因。在早期的电传打字机上,有一个部件叫“字车”,类似于打印机的喷头。“字车”从最左端开始,每打一个字符,“字车”就向右移动一格。当打满一行字后,“字车”需要回到最左端。这个动作被称作“回车”(return carriage)。

但是,仅仅做了“回车”还不够,我们还需要将纸张向上移一行,让“字车”对准新的空白一行,否则两行字将被重叠打印在一起。这个动作被称作“换行”。

随着时代的发展,字符不仅仅只打印在纸上。例如,在屏幕上显示字符时,无须“字车”。因此,当人们将开始新的一行引入计算机上时,分成了两种惯例:
两类具有代表性的系统分别使用了其中一种惯例:
当以文本模式在不同操作系统中读写文件时,C语言会自动转换行尾符,使得程序员无须关注底层的行尾符差异。例如,在 Windows 系统中,当以文本模式读取一个包含 \r\n 行尾符的文件时,C语言会将其转换为 \n,反之亦然。

正是因为 C语言把文件的输入和输出数据当作一行行的文本来处理,所以在换行时才会出现这种自动转换的现象。这种文件操作模式被称作文本模式。

2) 二进制模式

二进制模式主要用于处理二进制文件,如图片、音频、可执行文件等。

在二进制模式下,文件中的数据按照字节序列进行处理,不会对数据进行任何转换。这意味着程序员需要自行处理字节序列和数据结构

当以二进制模式读写文件时,C语言不会进行任何行尾符转换,而是会按文件内容原样进行读取或写入。这使得二进制模式适用于非文本文件和对数据内容敏感的场景。

在使用 fopen() 函数打开文件时,我们可以通过指定模式来选择文本模式或二进制模式。我们只需要在函数 fopen() 的第二个参数的字符串中添加字符 b,代表二进制 binary。

例如:
注意,在一些操作系统(如 UNIX/Linux/macOS)中,文本模式和二进制模式没有区别,因为这些系统使用统一的行尾符(\n)。然而,在跨平台编程时,为了确保代码的兼容性和可移植性,仍然建议根据实际需求选择合适的文件模式。

相关文章