一次文件冲突排查:空文件为什么会被当成不存在

举报
yd_267833669 发表于 2026/10/28 15:49:35 2026/10/28
【摘要】 分享一次 workvault 文件冲突边界的复现:空文件与不存在的区别、排查过程和测试建议。

在查看 Markdown 知识库工具 workvault 的代码时,我用一个小测试检查了它的 keep-both(保留两份)策略。这个策略遇到重名文件时,会为新文件寻找带序号的名字。测试中出现了一个边界情况:候选文件已经存在,但内容为空时,新内容会写进这个文件。

这个问题很小,却适合用来说明文件操作中一个容易混淆的区别:文件不存在,和文件存在但内容为空,是两种状态。

构造一个最小场景

假设目录中已经有两个文件:

a.md        内容:original
a (1).md    内容为空

现在要写入一份新的 a.md,内容是 new,并选择 keep-both。由于前两个名字都被占用,预期的新文件名是 a (2).md。

我在 workvault 的 e159905 提交上,用 Vitest 和内存 Writer 模拟了这个场景。实际结果是写入成功,返回路径为 a (1).md;这个原本为空的文件变成了 new。测试只用内存数据,没有改动真实笔记。

问题出在存在性判断

workvault 的 Writer 接口用 read(path) 读取文件:不存在时返回 null,存在时返回文件内容。寻找可用文件名的循环用了类似下面的判断:

while (await writer.read(candidate)) {
  // 尝试下一个候选名
}

JavaScript 会把空字符串 "" 和 null 都视为假值。所以候选文件虽然存在,只要内容为空,循环就会停下,把它当成可写的新位置。

按照这个接口的约定,可以明确区分 null 和空字符串:

while ((await writer.read(candidate)) !== null) {
  // 候选路径已存在,继续寻找
}

这里的改法针对当前 Writer.read 的返回约定。其他项目如果用独立的文件存在性接口,也应明确区分“不存在”和读取失败,避免把权限错误等情况误当成可覆盖。

测试时可以多看一眼什么

文件冲突测试除了普通的同名非空文件,也可以放入空文件、多个连续编号的文件,再检查最终文件名和原文件内容。对 keep-both 来说,测试不应只检查函数有没有返回成功,还要验证原有路径是否保持不变。

这次复现使用的是内存 Writer,验证了名称选择和写入调用;具体文件系统上的并发创建等情况需要另外测试。问题已按实际复现过程提交到 workvault Issue #69,后续状态以项目页面为准。

【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0)

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。