很多人在使用 Office、文本编辑器、IDE 等工具时,会偶尔在文件夹里看到一个以 ~ 开头的文件;或者在异常退出后,文档被恢复为临时版本。本文将从机制出发,一步步讲清楚这个 ~ 文件的来源、作用、与缓冲机制的关联,以及为什么有时你“没保存就退出”会丢失数据。文章兼顾 Windows 与 Linux 场景,希望能对大家在日常排错、数据恢复、文件操作安全性上有帮助。
~$xxx.docx,我愣住了那天我在整理一个共享文件夹,突然看到一个神秘的文件:
~$报告.docx这个文件名开头有一个波浪号加美元符号(~$),平时看文档目录几年也没见过这个东西。
我心想:这个东西是做什么的?能删吗?会不会影响文件?
上面这正是很多开发者、文档编辑者在日常中会遇到的问题。
下面,就让我们认真梳理一遍这个 ~$ 文件背后的机制。
~$ 文件是什么?~$ 开头的文件,常见于 Microsoft Office(Word、Excel、PowerPoint 等)文档目录。
.docx、.xlsx)时,Office 会在同一目录下创建这个文件。
作用 | 描述 |
|---|---|
崩溃恢复 | 在你编辑文档的过程中,这个文件会保存你当前的编辑状态。当程序异常退出或断电时,下次打开时 Office 可以检测它,并尝试恢复未保存内容。 |
文件锁 / 协同编辑提示 | 当一个用户打开文件编辑时,~$ 文件作为“占用标志”存在。其他用户通过网络共享打开同一文档时,会检测到这个临时文件存在,从而知道该文档正被占用,可能提示以只读模式打开。 |
Report.docx 打开文档。
~$Report.docx。
~$ 文件(或将缓冲区内容同步到临时文件)。
Report.docx,然后删除 ~$Report.docx。
~$Report.docx 保留下来。下次启动 Office 时,检测到它,就认为可能有未保存数据可恢复。
如果你看到一个 ~ 文件,但原始文档是关闭状态、没有编辑者在用,那么这个 ~ 文件往往就是“残留垃圾”,基本可以安全删除。
~$ 文件吗?回答:是可以的。 前提是确保对应的原始文档已关闭,且没有别人在编辑。 因为在正常场景下,Office 会在关闭时自动删除这个临时文件。 如果这个文件被保留下来,一般来说它不包含额外的“核心数据”,主要是编辑状态的中间快照,所以删除它不会造成文档本体的丢失。
~$ 文件可能没有被清理,下一次就能看到。
当然会。虽说命名习惯不同,但原理类似。下面是几个例子:
.filename.swp 的交换(swap)文件。
#filename# 的自动保存文件。
.autosave 格式、临时文件、回收站版本等。
这些程序之所以都这么做,是出于同一个目的:在意外结束时,尽可能保留可恢复状态。
~$ 文件?这个问题很有意义,因为很多人在 Windows 和 Linux 混用环境。
如果你通过 Wine、CrossOver 等在 Linux 下运行 Microsoft Office,那么 Office 的行为在文档目录创建 ~ 文件的机制是与 Windows 一致的。也就是说,你很可能在 Linux 的文档目录看到 ~Report.docx——Office 在写 Linux 上也会做同样的操作。
Linux 本身不会强制为每个编辑的文件生成 ~$ 文件。各个程序有各自机制,常见做法如下:
/tmp 或 /var/tmp,而不是文档目录。这样目录不会被凌乱。
. 开头的隐藏文件(如 .filename.swp)。
~/.config/libreoffice/…/backup 等路径,而不是文档目录本身。
.swp、Emacs 的 #…#,都在编辑期间存在,正常退出会删除或重命名。
下面是一个对比表格:
环境 / 程序 | 临时或恢复文件命名 | 存放位置 | 核心用途 |
|---|---|---|---|
Microsoft Office(在 Windows 或 Wine 上) | ~$文件名 | 与文档同一目录 | 崩溃恢复 + 文件锁 |
Vim | .filename.swp | 与文档目录 | 崩溃恢复 +占用检测 |
Emacs | #filename# | 与文档目录 | 自动保存 |
LibreOffice | 随机名或隐藏文件 | 用户配置目录 / 缓存目录 | 自动恢复 /临时备份 |
其他编辑器 / IDE | .autosave、~filename.tmp 等 | 文档目录或临时目录 | 临时保存 /回滚功能 |
综上,Linux 下虽然默认不产生 ~$ 文件,但多数应用程序有自己的备份、自动保存、恢复机制。命名、存放方式更加多样,更倾向于“幕后隐藏”的方式,而非直接出现在当前目录。
要理解为什么“没点保存,直接退出”会导致数据丢失,就必须理解 缓冲机制。~$ 文件只是机制的一环,缓冲机制是更基础的技术层面。
磁盘 I/O 要比内存慢得多。若每次微小变化就写磁盘,会极度损耗性能。 缓冲机制提供一个“中转仓库”,把多次小写入合并成一次大写入,从而提高效率。
在现代系统里,这个缓冲机制分为两个层次:
只有当这两个缓冲都刷新 / 写入到磁盘后,数据才真正落盘持久化。
模式 | 触发写入条件 | 典型用途 | 特点 / 风险 |
|---|---|---|---|
全缓冲(Fully Buffered) | 缓冲区满、手动 flush、关闭文件 | 文件 I/O | 高效,但若未 flush,退出时会丢失数据 |
行缓冲(Line Buffered) | 遇到换行符 \n 或缓冲满 | 标准输出 / 交互式 I/O | 对终端输出很友好 |
无缓冲(Unbuffered) | 每次写操作立刻执行 | 错误输出、日志流 | 实时性好,但性能代价高 |
在 C / C++ 标准库中,默认文件 I/O(fopen、fwrite 等)通常使用 全缓冲。也就是说,只有缓冲区满了、遇到 fflush()、fclose() 等操作时才写入系统。若你在这之前程序崩溃或退出,那些还没 flush 的数据就丢了。
标准 I/O 函数中:
fflush(FILE *stream):强制刷新该流的缓冲区(用户空间 → 内核空间)。
fclose(FILE *stream):关闭流之前,会自动刷新缓冲区。
setvbuf / setbuf:可以设置缓冲模式(全缓冲 / 行缓冲 / 无缓冲)和缓冲区大小。
当我们在应用程序(如 Office、文本编辑器)里点击“保存”按钮时,底层实际上执行的就是:
~$ 文件(如果有)或清理恢复状态。
如果我们没有点击“保存”,数据仍可能停留在用户缓冲区或内核缓冲区里,还未真正落盘。当程序崩溃或被强制终止时,这些缓冲还未完成写操作,数据就丢失。
下面我们来画一个流程图 / 步骤,便于理解每个阶段的数据状态,以及各类故障时数据如何丢失 / 恢复。
[用户输入] → 写入用户缓冲区 → (定期或手动)→ flush 到内核缓冲区 → 操作系统异步写入磁盘 → 删除 "~$" 临时文件
补充一点:编辑期间还可能写入 ~$ 临时文件做恢复状态记录(写入临时文件通常也涉及缓冲机制)。
[用户输入] → 写入用户缓冲区 → (尚未 flush)→ 程序崩溃 / 强制退出 → 用户缓冲区数据被释放 → 内核缓冲区可能尚未写入磁盘 → 原文档和 `~` 文件状态可能不一致 → 下次启动可根据 `~` 文件尝试恢复部分内容
在这种异常情形下,~$ 文件成为你恢复恢复点的依据;它记录了最近一次写入临时状态的情况。
因为在全缓冲机制下,很多修改都还停留在用户缓冲区,不会自动 flush。 若程序没有机会执行刷新操作(因为被强制终止),这些缓冲数据就永远消失了。
你可以把“点击保存”理解为给程序下达命令:“把当前所有未写入磁盘的数据都写下来。”在程序没有执行这条命令之前,就退出、崩溃,就没机会写入,资料残留在缓冲区。
在理解底层机制后,我们来看一些实际建议,帮助减少数据丢失风险、优化文件操作安全性。
~$ 文件残留,可能说明程序曾异常退出,建议及时清理或恢复。
如果你在编写涉及文件写入的程序,可以考虑以下策略:
fflush()、fsync() 等保证写入。
~$ 机制标识文件被占用。
从我平常处理文档、编辑器、文件存储的经验来看,这个 ~$ 文件机制虽然看起来神秘,但其实是一个非常务实、典型的“中间保护层”设计。它并不是专为 Office 孤立设计,而是这一类软件在面临崩溃、并发访问、恢复机制等挑战时的一种通用解决方案。
下面是我对这几个层面的总结与看法:
~$ 文件,是为了简单直观,让恢复机制紧贴文档本身。缺点是目录易被污染、误删可能造成恢复困难。这种设计在桌面办公场景下,是一种合适的折中。
~$ 或 .swp,也不能假设临时目录永远可用。