C中的open(), write(), close(), fopen()

news/2025/3/17 16:55:07/文章来源:https://www.cnblogs.com/hisun9/p/18503564

open() 函数

原型

#include <fcntl.h>
#include <unistd.h>int open(const char *pathname, int flags, mode_t mode);
  • pathname:要打开的文件的路径。

  • flags:打开文件的模式(如只读、只写等)。常用的标志包括:

    • O_RDONLY:只读模式。
    • O_WRONLY:只写模式。
    • O_RDWR:读写模式。
    • O_CREAT:如果文件不存在,则创建新文件。
    • O_TRUNC:如果文件已存在并且是以写入模式打开的,则截断文件为零长度。
    • O_APPEND:将写入操作附加到文件末尾。
  • mode:文件权限,通常在创建文件时使用。它是一个八进制值(例如 0666),表示文件的读写权限(关于0666的解释请看这篇博客Linux中文件的权限)。

返回值

  • 如果成功,返回一个非负整数(文件描述符),可以用来进行后续的读写操作。

  • 如果失败,返回 -1,并且可以通过 errno(是一个全局变量,定义在<errno.h>头文件中,这篇博客有涉及到) 获取错误信息。

错误处理

常见的错误包括:

  • EACCES:权限被拒绝。

  • ENOENT:文件不存在。

  • EEXIST:试图创建一个已存在的文件(当使用 O_CREAT 时)。

举一个例子

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>int main() {int fd = open("example.txt", O_RDWR, 0666);if (fd == -1) {perror("Error opening file");close(fd);return 1;}// 使用文件描述符 fd 进行读写操作...close(fd); // 关闭文件return 0;
}

输出如下:

img

write()函数

原型

#include <unistd.h>ssize_t write(int fd, const void *buf, size_t count);
  • fd:要写入的文件描述符,通常是 open() 返回的值。

  • buf:指向要写入的数据的指针。

  • count:要写入的字节数。

返回值

  • 如果成功,返回实际写入的字节数。

  • 如果失败,返回 -1,并且可以通过 errno 获取错误信息。

错误处理

常见的错误包括:

  • EFAULT:buf 指针无效。

  • EBADF:文件描述符无效。

  • EIO:I/O 错误。

举一个例子

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>int main() {int fd = open("example.txt", O_WRONLY | O_CREAT | O_TRUNC, 0666);if (fd == -1) {perror("Error opening file");close(fd);return 1;}const char *data = "Hello, World!\n";ssize_t bytes_written = write(fd, data, 14);if (bytes_written == -1) {perror("Error writing to file");close(fd);return 1;}printf("Wrote %zd bytes to file.\n", bytes_written);close(fd); // 关闭文件return 0;
}

输出如下:

img

close()函数

close() 函数用于关闭一个已打开的文件描述符。在 C/C++ 编程中,关闭文件描述符是一个重要的步骤,以确保资源被正确释放。

原型

#include <unistd.h>int close(int fd);
  • fd:要关闭的文件描述符,通常是之前通过 open()socket()pipe() 等函数获取的值。

返回值

  • 如果成功,close() 返回 0。

  • 如果失败,返回 -1,并且可以通过 errno 获取错误信息。

工作原理

  • 释放资源:关闭文件描述符后,操作系统会释放与该文件描述符相关的所有资源。这包括文件的缓冲区、文件锁和其他相关信息。

  • 防止资源泄漏:如果不调用 close(),程序在结束时可能会造成资源泄漏,因为操作系统可能会保留这些资源,直到程序终止。

  • 同步数据:在某些情况下,关闭文件描述符会导致缓冲区中的数据被强制写入磁盘。对于写入模式打开的文件,关闭操作可能会确保所有待写入的数据都已被写入。

错误处理

常见的错误包括:

  • EBADF:文件描述符无效或未打开。

  • EIO:发生 I/O 错误。

举一个例子

#include <fcntl.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>int main() {int fd = open("example.txt", O_WRONLY | O_CREAT, 0666);if (fd == -1) {perror("Error opening file");return 1;}// 执行写操作...if (close(fd) == -1) {perror("Error closing file");return 1;}printf("File closed successfully.\n");return 0;
}

输出如下:

img

fopen()函数

fopen() 是 C 标准库中的一个函数,用于打开一个文件并返回一个文件指针,以便后续进行读写操作。它通常在 <stdio.h> 头文件中声明。

原型

FILE *fopen(const char *filename, const char *mode);
  • filename:要打开的文件的名称(字符串)。

  • mode:打开文件的模式,指示将如何访问该文件。常用的模式包括:

    • "r":只读模式,文件必须存在。

    • "w":只写模式,若文件存在则清空内容,不存在则创建新文件。

    • "a":附加模式,数据会被写入到文件末尾。

    • "r+":读写模式,文件必须存在。

    • "w+":读写模式,若文件存在则清空内容,不存在则创建新文件。

    • "a+":附加读写模式,可以读文件内容,写入数据到文件末尾。

返回值

  • 返回一个指向 FILE 结构的指针,表示打开的文件。

  • 如果打开失败,返回 NULL,并且可以通过 errno 获取错误信息。

举一个例子

#include <stdio.h>int main() {FILE *file = fopen("example.txt", "r"); // 尝试以只读模式打开文件if (file == NULL) {perror("Error opening file"); // 打印错误信息fclose(file); // 关闭文件return 1;}// 进行文件操作...fclose(file); // 关闭文件return 0;
}

输出如下:

img

重要注意事项

  • 错误检查:在使用 fopen() 后,始终检查返回值,以确保文件成功打开。

  • 关闭文件:使用 fclose() 函数关闭打开的文件,以释放系统资源。

fopen()和open()有什么不同

fopen() 更适合一般的文件处理需求,提供了较高的抽象层次,而 open() 则适合需要低级文件控制的情况。

  1. 语言和库

    fopen()

     - 是 C 标准库中的函数,通常用于 C 和 C++ 编程。- 提供更高层次的文件操作接口。
    

    open()

     - 是 POSIX 系统调用,主要用于 C 语言(也可用于C++),适用于 UNIX/Linux 系统。- 提供低级别的文件操作。
    
  2. 返回值

    fopen()

    • 返回一个指向 FILE 结构的指针,用于后续的文件操作。

    • 如果打开失败,返回 NULL。

    open()

    • 返回一个文件描述符(非负整数),用于标识打开的文件。

    • 如果打开失败,返回 -1,并且可以通过 errno 检查错误。

  3. 文件模式

    fopen()

    • 使用字符串来指定打开模式(如 "r"、"w"、"a" 等)。

    • 提供更方便的读写功能。

    open()

    • 使用整数标志来指定打开模式(如 O_RDONLY、O_WRONLY、O_RDWR 等)。

    • 适合底层文件操作,允许更多的细粒度控制。

  4. 错误处理

    fopen()

    • 错误处理通常依赖于返回值(检查指针是否为 NULL)。

    open()

    • 需要检查返回值并结合 errno 获取具体错误信息。
  5. 文件操作

    fopen()

    • 提供了 freadfwritefprintffscanf 等高级文件操作函数,适合格式化输入输出。

    open()

    • 主要与 read()write()lseek()close() 等系统调用一起使用,适合底层的文件操作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/822013.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C#数据结构与算法4-C# 简单排序方法

一 排序 排序(Sort)是计算机程序设计中的一种重要操作,也是日常生活中经常遇到的问题。例如,字典中的单词是以字母的顺序排列,否则,使用起来非常困难。同样,存储在计算机中的数据的次序,对于处理这些数据的算法的速度和简便性而言,也具有非常深远的意义。 二 基本概念…

C#数据结构与算法5-C# 快速排序

一 快速排序 快速排序由于排序效率综合来说你几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试,包括像腾讯,微软等知名IT公司都喜欢考这个,还有大大小的程序方面的考试如软考,考研中也常常出现快速排序的身影…

C#数据结构与算法4-C# 快速排序

一 快速排序 快速排序由于排序效率综合来说你几种排序方法中效率较高,因此经常被采用,再加上快速排序思想----分治法也确实实用,因此很多软件公司的笔试面试,包括像腾讯,微软等知名IT公司都喜欢考这个,还有大大小的程序方面的考试如软考,考研中也常常出现快速排序的身影…

C#数据结构与算法1-C# 线性表

一 什么是线性表 线性表是最简单、最基本、最常用的数据结构。线性表是线性结构的抽象(Abstract),线性结构的特点是结构中的数据元素之间存在一对一的线性关系。这种一对一的关系指的是数据元素之间的位置关系,即:( 1)除第一个位置的数据元素外,其它数据元素位置的前面都…

C#数据结构与算法2-C# 栈和队列

一 栈和队列 栈和队列是非常重要的两种数据结构,在软件设计中应用很多。栈和队列也是线性结构,线性表、栈和队列这三种数据结构的数据元素以及数据元素间的逻辑关系完全相同,差别是线性表的操作不受限制,而栈和队列的操作受到限制。栈的操作只能在表的一端进行,队列的插入…

C# 托盘通知

一 托盘通知 NotifyIcon托盘通知:程序可以在通知区创建一个通知图标。一般地,可以提示一个气泡通知,右键菜单支持。准备:需要一个图标(*.ico),用于显示在通知区。如果没有ico格式,可以将png图片转成ico。 演示:在项目中添加托盘通知。① 设置文本Text;② 选择图标Icon; …

学习强化学习有哪些工具

强化学习是一种动态的学习方法,目前有许多工具可以帮助研究者和开发者入门和深入学习。主要工具包括:1、OpenAI Gym:一个用于开发和比较强化学习算法的工具包;2、TensorFlow Agents:一个基于TensorFlow的强化学习库;3、Stable Baselines:一个高质量的强化学习库。其中,…

在C语言中如何处理大型项目的模块化

### 在C语言中如何处理大型项目的模块化 在处理大型项目的模块化时,C语言中的关键策略包括使用函数库、分离编译、使用条件编译指令、以及采用模块化设计原则。其中,使用函数库是最直接有效的方法之一,允许开发者重用代码、减少重复工作,并保持代码的整洁和可管理性。 详细…

基类指针、虚纯虚函数、多态性、虚析构

多态 基类指针 // 父类指针可以 new 一个子类对象 Human *pman = new Man(); Human *pwman = new Wonan();抛出问题:父类指针没有办法调用子类的成员函数,那么你为什么还让父类指针 new 一个子类对象呢? 下面与虚函数搭配 虚函数(动态绑定) 我们只定义一个对象指针,就能…

SATA和NVMe SSD在速度上有多大差异

SATA和NVMe SSD在速度上的差异主要体现在:一、传输接口和带宽能力差异;二、读写速度的差异;三、应用场景和效率的差异;四、价格和市场趋势的差异;五、未来发展的差异。实际上,NVMe SSD在速度上远超SATA SSD,特别适合需要高速数据处理的应用场景,如高端游戏、视频编辑和…

Serverless技术栈推荐

# Serverless技术栈推荐 在探讨Serverless技术栈推荐时,我们首先要明确Serverless的核心优势:无需管理服务器、按需自动扩展、成本效益高、开发效率提高。其中,无需管理服务器是Serverless技术的标志性特征,它允许开发者专注于代码和业务逻辑的实现,而无需担心底层基础设施…