第 5 章 · 03 文件 I/O:读取、保存、原子性


文档摘要

第 5 章 · 03 文件 I/O:读取、保存、原子性 本节摘要:编辑器要把用户的改动安全落盘。本节讲三个要点:读取时要处理编码(UTF-8)与行尾(CRLF/LF);保存要保证「原子性」——先写临时文件,rename 覆盖原文件,这样即使中途崩溃也不损坏原文件;以及「编码检测」的基础。理解原子性保存,你就掌握了所有「数据安全写入」的通用模式。 内容来源:基于编辑器实现与文件 IO 整理的导读。 学习目标 阅读完本节,你应当能够: 读取文件时处理 UTF-8 编码与 CRLF/LF 行尾差异。 说清「原子性保存」:写临时文件→fsync→rename 覆盖。 解释为什么直接覆写原文件危险(中途崩溃损坏数据)。 实现编辑器的安全保存。

第 5 章 · 03 文件 I/O:读取、保存、原子性

本节摘要:编辑器要把用户的改动安全落盘。本节讲三个要点:读取时要处理编码(UTF-8)与行尾(CRLF/LF);保存要保证「原子性」——先写临时文件,rename 覆盖原文件,这样即使中途崩溃也不损坏原文件;以及「编码检测」的基础。理解原子性保存,你就掌握了所有「数据安全写入」的通用模式。

内容来源:基于编辑器实现与文件 IO 整理的导读。

学习目标

阅读完本节,你应当能够:

  1. 读取文件时处理 UTF-8 编码与 CRLF/LF 行尾差异。
  2. 说清「原子性保存」:写临时文件→fsync→rename 覆盖。
  3. 解释为什么直接覆写原文件危险(中途崩溃损坏数据)。
  4. 实现编辑器的安全保存。

一、学习价值:原子性是「数据安全」的通用模式

「保存」看似简单——把内存写回文件。但朴素做法(直接打开原文件覆写)有个致命风险:写到一半断电/崩溃,原文件就损坏了——既不是旧版也不是新版,是残缺的乱码。这对编辑器是灾难:用户几年的代码可能毁于一次崩溃。

「原子性保存」是解决这个问题的通用模式,不只编辑器用——数据库的 WAL、配置管理工具、包管理器都用类似思路。理解它,你掌握了「安全写入数据」的基本功。

二、子系统拆解

读取:编码与行尾

  • 编码:现代文件几乎都是 UTF-8(变长编码)。读取时按字节读,解码成字符。注意 BOM(文件头标记,可有可无)。
  • 行尾:Windows 用 CRLF(\r\n)、Unix 用 LF(\n)。读取时统一转成 LF(内部表示),保存时按用户偏好或原格式写回。

原子性保存(核心)

朴素(危险):

打开 原文件(写模式, 截断) ←─ 此时原内容已丢! 写入新内容 关闭 # 若写到一半崩溃, 原文件是损坏的残缺内容

原子性(安全):

1. 写到临时文件 原文件.tmp(全新创建) 2. fsync(临时文件) ←─ 强制刷盘, 确保数据真落盘 3. rename(原文件.tmp, 原文件) ←─ 原子操作: 要么成功(整新版), 要么失败(原文件还是旧版)

rename 在同一文件系统上是原子的——它只是改个目录项指针,要么完成(整新版)要么没发生(原文件不动)。中途崩溃不会留下「半个新半个旧」。这是原子性保存的关键。

关键概念:rename 是原子的(在同一文件系统上)。这就是为什么「写临时文件 + rename」能保证原子性——崩溃时要么没 rename(原文件完整)、要么 rename 完成(新文件完整),不存在中间态。

编码检测

文件可能是 UTF-8、GBK、Latin-1 等。编辑器读取时常:

  • 看 BOM(若有)。
  • 否则尝试 UTF-8 解码,失败则降级其他编码。
  • 或让用户指定。

第一个编辑器可假设全 UTF-8,简化处理。

三、上手第一步:实现原子保存

  1. 保存函数:write 临时文件 → fsync → rename 覆盖原文件
  2. 临时文件与原文件须在同一目录(保证 rename 原子 + 快)。
  3. 读取时按 UTF-8 解码,行尾归一为 LF。

本节要点回顾

  1. 读取处理编码(UTF-8)与行尾(CRLF/LF);内部统一 LF,保存按需写回。
  2. 原子性保存:写临时文件 → fsync → rename 覆盖;rename 原子,崩溃要么旧版要么新版,无残缺。
  3. 直接覆写原文件危险:写到一半崩溃损坏数据。
  4. rename 原子的前提:同一文件系统;临时文件与原文件同目录。
  5. 这是数据安全的通用模式:数据库 WAL、配置管理都用类似思路。

推荐上手顺序

  1. 先实现「能读能存」(UTF-8、LF),不管原子性,跑通基本流程。
  2. 加行尾处理:读时 CRLF→LF,存时按用户偏好。
  3. 改保存为原子版:临时文件+fsync+rename。
  4. 测试:保存中途 kill 进程,确认原文件未损坏。

下一节讲终端渲染——termios 与 VT100 转义码。


发布者: 作者: 灏天文库 转发
评论区 (0)
U