当前位置: 首页 > article >正文

linux下文件读写操作

Linux下,文件I/O是操作系统与文件系统之间进行数据传输的关键部分。文件I/O操作允许程序读取和写入文件,管理文件的打开、关闭、创建和删除等操作。

1. 文件描述符

在Linux中,每个打开的文件都由一个文件描述符来表示。文件描述符是一个非负整数,通常从0开始,分别表示标准输入stdin、标准输出stdout和标准错误stderr。用户程序打开文件后,操作系统会为其分配一个文件描述符。

2. 文件操作函数

Linux提供了一系列的系统调用和库函数来进行文件操作,主要包括:

  • 打开文件

    • open()
      

      打开文件并返回文件描述符。文件描述符是进程访问文件的句柄,后续的read()write()操作都需要通过它进行。

      int fd = open("filename", O_RDONLY);
      
  • 读取文件

    • read()
      

      从文件中读取数据。

      char buf[1024];
      ssize_t bytes_read = read(fd, buf, sizeof(buf));
      
      • 流程
        1. 进程调用read(),请求从文件中读取数据。
        2. 内核检查页缓存中是否存在请求的数据
          • 如果数据在页缓存中,内核将数据从页缓存复制到用户空间的缓冲区。
          • 如果数据不在页缓存中,内核会从磁盘读取数据到页缓存,然后再复制到用户空间。
        3. 返回实际读取的字节数。
  • 写入文件

    • write()
      

      向文件中写入数据。

      const char *text = "Hello, world!";
      ssize_t bytes_written = write(fd, text, 13);
      
      • 流程
        1. 进程调用write(),请求将数据写入文件。
        2. 内核将数据从用户空间复制到页缓存中。
        3. 数据被标记为“脏页”,表示需要写回磁盘。
        4. 内核的页回写机制会在适当的时候将脏页写回磁盘。
  • 页缓存的作用

    • 页缓存是内核维护的一块内存区域,用于缓存文件数据。
    • 作用
      1. 减少磁盘I/O:通过缓存文件数据,减少对磁盘的直接访问,提高性能。
      2. 延迟写入write()操作不会立即将数据写入磁盘,而是先写入页缓存,由内核在后续的某个时间点写回磁盘。
      3. 预读机制:内核会提前读取文件数据到页缓存中,优化后续的read()操作。
  • 关闭文件

    • close()
      

      使用close()系统调用关闭文件,释放文件描述符。

      close(fd);
      
  • 文件状态信息

    • fstat(): 获取文件的状态信息。
    • stat(): 获取文件的状态信息(用于路径名)。
  • 页回写机制

    • 内核会在以下情况下将脏页写回磁盘
      1. 页缓存中的脏页达到一定比例。
      2. 进程调用fsync()fdatasync()强制刷新页缓存。
      3. 系统内存不足时,内核会回收脏页。

3. 文件打开模式

在使用open()函数时,可以指定不同的文件打开模式

  • O_RDONLY: 只读模式。
  • O_WRONLY: 只写模式。
  • O_RDWR: 读写模式。
  • O_CREAT: 如果文件不存在则创建文件。
  • O_TRUNC: 如果文件存在并以写入模式打开,则将其截断为零长度。
  • O_APPEND: 以追加模式打开文件。

4. 文件I/O缓冲

Linux使用缓冲区来提高文件I/O的效率。标准库函数如fread()fwrite()通常会使用缓冲I/O,而系统调用如read()write()则直接与内核进行交互。缓冲区的使用可以减少系统调用的次数,从而提高性能。

5. 文件锁定

在多进程或多线程环境中,文件锁定机制可以防止多个进程同时写入同一个文件,导致数据不一致。常用的文件锁定方法包括

  • 共享锁(read lock):允许多个进程同时读取文件。
  • 独占锁(write lock):只允许一个进程写入文件。

可以使用flock()fcntl()进行文件锁定。

6. 目录操作

除了普通文件,Linux还支持目录操作。常用的目录操作函数包括:

  • opendir(): 打开目录。
  • readdir(): 读取目录中的条目。
  • closedir(): 关闭目录。

7. 文件权限与所有权

Linux文件系统具有严格的权限控制。每个文件都有所有者、组和其他用户的权限,可以通过chmodchown等命令进行管理。

8. 文件系统

Linux支持多种文件系统,如ext4、XFS、Btrfs等。每种文件系统都有其特定的特点和优缺点,适合不同的使用场景。

9. 异步I/O

Linux还支持异步I/O(AIO),允许程序在进行I/O操作时继续执行其他任务,而不必等待I/O操作完成。可以使用aio_read()aio_write()函数实现异步I/O。

例子1. 文件的创建与写入

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main() {int fd;const char *text = "Hello, Linux File I/O!\n";// 创建并打开文件fd = open("example.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);if (fd == -1) {perror("Error opening file");return 1;}// 写入数据write(fd, text, strlen(text));// 关闭文件close(fd);return 0;
}

例子2. 文件的读取

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>int main() {int fd;char buffer[100];ssize_t bytesRead;// 打开文件fd = open("example.txt", O_RDONLY);if (fd == -1) {perror("Error opening file");return 1;}// 读取数据bytesRead = read(fd, buffer, sizeof(buffer) - 1);if (bytesRead == -1) {perror("Error reading file");close(fd);return 1;}// 添加字符串结束符buffer[bytesRead] = '\0';// 打印读取的数据printf("Read from file: %s", buffer);// 关闭文件close(fd);return 0;
}

例子3. 追加写入文件

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main() {int fd;const char *text = "Appending this line.\n";// 以追加模式打开文件fd = open("example.txt", O_WRONLY | O_APPEND);if (fd == -1) {perror("Error opening file");return 1;}// 追加写入数据write(fd, text, strlen(text));// 关闭文件close(fd);return 0;
}

例子4. 目录操作示例

#include <stdio.h>
#include <dirent.h>int main() {DIR *dir;struct dirent *entry;// 打开当前目录dir = opendir(".");if (dir == NULL) {perror("Error opening directory");return 1;}// 读取目录项while ((entry = readdir(dir)) != NULL) {printf("Found file: %s\n", entry->d_name);}// 关闭目录closedir(dir);return 0;
}

例子5. 文件锁定示例

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main() {int fd;struct flock lock;// 打开文件fd = open("example.txt", O_WRONLY);if (fd == -1) {perror("Error opening file");return 1;}// 初始化锁lock.l_type = F_WRLCK; // 写锁lock.l_whence = SEEK_SET;lock.l_start = 0;lock.l_len = 0; // 锁定整个文件// 加锁if (fcntl(fd, F_SETLK, &lock) == -1) {perror("Error locking file");close(fd);return 1;}// 写入数据const char *text = "This is a locked write.\n";write(fd, text, strlen(text));// 解锁lock.l_type = F_UNLCK;fcntl(fd, F_SETLK, &lock);// 关闭文件close(fd);return 0;
}

在Linux中,如果要对其他目录中的文件进行I/O操作,只需在文件路径中指定完整的路径名。

1. 在其他目录中创建和写入文件

假设你想在/tmp目录下创建一个文件并写入数据,可以这样做:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main() {int fd;const char *text = "Hello, Linux File I/O in /tmp!\n";// 创建并打开/tmp目录下的文件fd = open("/tmp/example.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);if (fd == -1) {perror("Error opening file");return 1;}// 写入数据write(fd, text, strlen(text));// 关闭文件close(fd);return 0;
}

2. 从其他目录读取文件

如果要从/tmp目录读取文件,可以使用类似的方式:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>int main() {int fd;char buffer[100];ssize_t bytesRead;// 打开/tmp目录下的文件fd = open("/tmp/example.txt", O_RDONLY);if (fd == -1) {perror("Error opening file");return 1;}// 读取数据bytesRead = read(fd, buffer, sizeof(buffer) - 1);if (bytesRead == -1) {perror("Error reading file");close(fd);return 1;}// 添加字符串结束符buffer[bytesRead] = '\0';// 打印读取的数据printf("Read from file: %s", buffer);// 关闭文件close(fd);return 0;
}

3. 追加写入其他目录的文件

如果需要在/tmp/example.txt中追加数据,可以这样操作:

#include <stdio.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>int main() {int fd;const char *text = "Appending this line to /tmp/example.txt.\n";// 以追加模式打开/tmp目录下的文件fd = open("/tmp/example.txt", O_WRONLY | O_APPEND);if (fd == -1) {perror("Error opening file");return 1;}// 追加写入数据write(fd, text, strlen(text));// 关闭文件close(fd);return 0;
}

4. 处理文件路径中的空格和特殊字符

如果文件路径中包含空格或特殊字符,可以使用转义字符或用引号括起来。例如:

// 假设文件路径为 "/tmp/my file.txt"
fd = open("/tmp/my\\ file.txt", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);

或者:

fd = open("\"/tmp/my file.txt\"", O_WRONLY | O_CREAT | O_TRUNC, S_IRUSR | S_IWUSR);

相关文章:

linux下文件读写操作

Linux下&#xff0c;文件I/O是操作系统与文件系统之间进行数据传输的关键部分。文件I/O操作允许程序读取和写入文件&#xff0c;管理文件的打开、关闭、创建和删除等操作。 1. 文件描述符 在Linux中&#xff0c;每个打开的文件都由一个文件描述符来表示。文件描述符是一个非负…...

嵌入式学习第二十四天--网络 服务器

服务器模型 tcp服务器: socket bind listen accept recv/send close 1.支持多客户端访问 //单循环服务器 socket bind listen while(1) { accept while(1) { recv/send } } close 2.支持多客户端同时访问 (并发能力) 并发服务器 socket bind …...

Uniapp组件 Textarea 字数统计和限制

Uniapp Textarea 字数统计和限制 在 Uniapp 中&#xff0c;可以通过监听 textarea 的 input 事件来实现字数统计功能。以下是一个简单的示例&#xff0c;展示如何在 textarea 的右下角显示输入的字符数。 示例代码 首先&#xff0c;在模板中定义一个 textarea 元素&#xff…...

【Java 面试 八股文】计算机网络篇

操作系统篇 1. 什么是HTTP? HTTP 和 HTTPS 的区别?2. 为什么说HTTPS比HTTP安全? HTTPS是如何保证安全的&#xff1f;3. 如何理解UDP 和 TCP? 区别? 应用场景?3.1 TCP 和 UDP 的特点3.2 适用场景 4. 如何理解TCP/IP协议?5. DNS协议 是什么&#xff1f;说说DNS 完整的查询…...

Webservice创建

Webservice创建 服务端创建 3层架构 service注解&#xff08;commom模块&#xff09; serviceimpl&#xff08;server&#xff09; 服务端拦截器的编写 客户端拦截器 客户端调用服务端&#xff08;CXF代理&#xff09; 客户端调用服务端&#xff08;动态模式调用&a…...

使用VS Code remote ssh进行远程开发的笔记

本文是在VS Code中使用 remote ssh 进行开发的笔记。 安装插件 打开VS Code&#xff0c;在扩展区找到remote相关插件&#xff0c;安装之。下图中红色框出来的是已经安装了的插件&#xff08;圆圈处即为Remote Explorer&#xff09;。 实践 连接服务器 新建连接&#xff1a…...

C语言每日一练——day_3(快速上手C语言)

引言 针对初学者&#xff0c;每日练习几个题&#xff0c;快速上手C语言。第三天。&#xff08;会连续更新&#xff09; 采用在线OJ的形式 什么是在线OJ&#xff1f; 在线判题系统&#xff08;英语&#xff1a;Online Judge&#xff0c;缩写OJ&#xff09;是一种在编程竞赛中用…...

Linux基本操作指令4

1、查看Ubuntu的版本 lsb_release -a 2、在 Ubuntu 下安装 OpenGL Library sudo apt-get install libglu1-mesa-dev 3、终止当前运行的进程 Ctrl C//默认情况 Ctrl Shift C//若修改了复制快捷键为CtrlC的情况 4、快速打开终端 CtrlAltT 5、关闭终端 Ctrl Shift W…...

PostgreSQL - Windows PostgreSQL 下载与安装

Windows PostgreSQL 下载与安装 1、PostgreSQL 下载 下载地址&#xff1a;https://www.enterprisedb.com/downloads/postgres-postgresql-downloads 2、PostgreSQL 安装 启动安装程序 -> 点击 【Next】 指定安装路径 -> 点击 【Next】 默认勾选 -> 点击 【Next】 指…...

JVM 的主要组成部分及其作用?

创作内容丰富的干货文章很费心力&#xff0c;感谢点过此文章的读者&#xff0c;点一个关注鼓励一下作者&#xff0c;激励他分享更多的精彩好文&#xff0c;谢谢大家&#xff01; JVM包含两个子系统和两个组件&#xff0c;两个子系统为Class loader(类装载)、Execution engine(执…...

华为eNSP:配置P2P网络类型

一、什么是P2P网络类型 P2P&#xff08;Point-to-Point&#xff09;网络类型 是 OSPF&#xff08;开放最短路径优先&#xff09;协议中的一种网络类型&#xff0c;用于描述两个路由器之间直接相连的点对点链路。P2P 网络类型通常用于串行链路&#xff08;如 PPP 或 HDLC 封装&…...

通过数据集微调LLM后怎么调用

通过数据集微调LLM后怎么调用 1. 导入必要的库 from transformers import AutoTokenizer, AutoModelForCausalLMAutoTokenizer:这是 transformers 库中的一个实用类,它能够根据指定的模型名称或路径自动选择合适的分词器。分词器的主要作用是将输入的文本字符串转换为模型可…...

thinkphp+mysql+cast解决text类型字段的文本型数字排序错误的方法 - 数据库文本字段排序ASC、DESC的失效问题

TP中使用cast order $lists AmdCommonTable::where(..............) ->field(*,CAST(w6 AS UNSIGNED) as sort) ->order(sort, asc) ->select() ->toArray(); 先转换为数字&#xff0c;再order by 效果对比 (1/2) 不ok - 直接order by 某字段 asc - 只能按照文本…...

【Manus资料合集】激活码内测渠道+《Manus Al:Agent应用的ChatGPT时刻》(附资源)

DeepSeek 之后&#xff0c;又一个AI沸腾&#xff0c;冲击的不仅仅是通用大模型。 ——全球首款通用AI Agent的破圈启示录 2025年3月6日凌晨&#xff0c;全球AI圈被一款名为Manus的产品彻底点燃。由Monica团队&#xff08;隶属中国夜莺科技&#xff09;推出的“全球首款通用AI…...

C++----红黑树map和set的封装

一、红黑树 1.概念 红黑树&#xff0c;是一种二叉搜索树&#xff0c;但在每个结点上增加一个存储位表示结点的颜色&#xff0c;可以是Red或Black。 通过对任何一条从根到叶子的路径上各个结点着色方式的限制&#xff0c;红黑树确保没有一条路径会比其他路径长出2倍&#xff0…...

【报错】微信小程序预览报错”60001“

1.问题描述 我在微信开发者工具写小程序时&#xff0c;使用http://localhost:8080是可以请求成功的&#xff0c;数据全都可以无报错&#xff0c;但是点击【预览】&#xff0c;用手机扫描二维码浏览时&#xff0c;发现前端图片无返回且报错60001&#xff08;打开开发者模式查看日…...

软考 数据通信基础——信道

信道特性 带宽 在模拟信号里频率的差&#xff0c;表示信道能通过的频率 在数字信号里表示最大传输速率&#xff0c;单位用bit/s 通常用W表示 波特率 即码元速率&#xff0c;码元可看作一个时间周期 码元速率B2W也可写成B1/T 码元种类n和码元信息量个数N存在以下关系 Nl…...

windows 平台如何点击网页上的url ,会打开远程桌面连接服务器

你可以使用自定义协议方案&#xff08;Protocol Scheme&#xff09;实现网页上点击URL后自动启动远程桌面连接&#xff08;mstsc&#xff09;&#xff0c;参考你提供的C代码思路&#xff0c;如下实现&#xff1a; 第一步&#xff1a;注册自定义协议 使用类似openmstsc://协议…...

uni-app开发的App和H5嵌套封装的App,以及原生App有什么区别

uni-app 开发的 App 和 H5 嵌套封装的 App 是两种不同的开发模式&#xff0c;虽然它们都可以实现跨平台开发&#xff0c;但在技术实现、性能、功能支持等方面有显著区别。以下是详细对比&#xff1a; 1. uni-app 开发的 App uni-app 是一个基于 Vue.js 的跨平台开发框架&#…...

Anaconda中虚拟环境安装g++和gcc相同版本

安装torchSDF的时候遇到的&#xff0c;这是g和gcc版本不一致的问题 gcc: fatal error: cannot execute cc1plus: execvp: No such file or directory compilation terminated.查看gcc, g版本 gcc --version | head -n1 g --version | head -n1发现gcc的是anaconda中的&#x…...

Docker数据管理,端口映射与容器互联

1.Docker 数据管理 在生产环境中使用 Docker&#xff0c;往往需要对数据进行持久化&#xff0c;或者需要在多个容器之间进行数据共享&#xff0c;这必然涉及容器的数据管理操作。 容器中的管理数据主要有两种方式&#xff1a; 数据卷&#xff08;Data Volumns&#xff09;&a…...

部署前后端项目

部署项目 liunx 软件安装 软件安装方式 在Linux系统中&#xff0c;安装软件的方式主要有四种&#xff0c;这四种安装方式的特点如下&#xff1a; 建议nginx、MySQL、Redis等等使用docker安装&#xff0c;会很便捷&#xff0c;这里只演示JDK、ngxin手动的安装 安装JDK 上述我…...

从零构建逻辑回归: sklearn 与自定义实现对比

文章目录 理论基础1. 逻辑回归模型2. 损失函数3. 梯度推导(1) 计算 ∂ L ∂ y ^ \frac{\partial L}{\partial \hat{y}} ∂y^​∂L​(2) 计算 ∂ y ^ ∂ z \frac{\partial \hat{y}}{\partial z} ∂z∂y^​​(3) 计算 ∂ L ∂ z \frac{\partial L}{\partial z} ∂z∂L​(4) 计…...

1256:献给阿尔吉侬的花束--BFS多组输入--memset

1256&#xff1a;献给阿尔吉侬的花束--BFS多组输入--memset 题目 解析代码【结构体】用book标记且计步数的代码[非结构体法] 题目 解析 标准的BFS题目&#xff0c;在多组输入中要做的就是先找到这一组的起点和终点&#xff0c;然后将其传给bfs&#xff0c;在多组输入中最易忘记…...

【JavaEE】SpringBoot快速上手,探秘 Spring Boot,搭建 Java 项目的智慧脚手架

1.Spring Boot介绍 在学习SpringBoot之前, 我们先来认识⼀下Spring &#xff0c;我们看下Spring官⽅的介绍 可以看到&#xff0c;Spring让Java程序更加快速, 简单和安全。 Spring对于速度、简单性和⽣产⼒的关注使其成为世界上最流⾏的Java框架。 Spring官⽅提供了很多开源的…...

【C】初阶数据结构9 -- 直接插入排序

前面我们学习了数据结构二叉树&#xff0c;接下来我们将开启一个新的章节&#xff0c;那就是在日常生活中经常会用到的排序算法。 所谓排序算法就是给你一堆数据&#xff0c;让你从小到大&#xff08;或从大到小&#xff09;的将这些数据排成一个有序的序列&#xff08;这些数据…...

Lottie与LottieFiles:快速为前端Web开发注入精美动画的利器

目录 Lottie与LottieFiles&#xff1a;快速为前端Web开发注入精美动画的利器 一、Lottie是什么&#xff1f;从GIF到JSON的动画技术演进 1、传统动画臃肿的Gif 2、Lottie的突破性创新 二、Lottie的核心组件解析&#xff08;Lottie的技术架构&#xff09; 1、Lottie核心三要…...

Spring boot创建时常用的依赖

新建SpringBoot Maven项目中pom常用依赖配置及常用的依赖的介绍 1.springboot项目的总(父)依赖大全 <parent><artifactId>spring-boot-dependencies</artifactId><groupId>org.springframework.boot</groupId><version>2.3.3.RELEASE<…...

音乐API

https://neteasecloudmusicapi.vercel.app/docs/#/https://neteasecloudmusicapi.vercel.app/docs/#/ 使用实例 所有榜单内容摘要 说明 : 调用此接口,可获取所有榜单内容摘要 接口地址 : /toplist/detail 调用例子 : /toplist/detail 获取歌单所有歌曲 说明 : 由于网易云…...

UML(统一建模语言)详解:从理论到实践

1. UML概述 1.1 定义与历史背景 统一建模语言&#xff08;Unified Modeling Language, UML&#xff09; 是一种标准化的可视化建模语言&#xff0c;用于描述、设计、构造和文档化软件系统。它诞生于1994-1997年&#xff0c;由Grady Booch、James Rumbaugh和Ivar Jacobson&…...