NodeJS fs模块写入大文件后读取为空、行数统计错误问题
问题根因
你遇到的读写异常和datasync无关,是代码逻辑存在三处核心问题:
- 写入时未做序列化处理:
fakeUsers返回的是对象数组,你直接将数组传给appendFile方法,会触发隐式类型转换,数组内的用户对象会统一转为[object Object]字符串拼接,只有faker生成的paragraphs自带的换行符会被保留,这就是你最多只能统计到1364行的核心原因。 - 读文件逻辑存在缺陷:
fd.read调用会返回实际读取的字节数bytesRead,你没有使用这个返回值,直接把初始化的全空格buffer整体转字符串,未读取到的位置全是填充的空格,看起来就像空行。 - 额外的无效调用:读模式打开的文件描述符调用
datasync没有任何意义,该方法的作用是将写入侧的内核缓存刷入磁盘,读操作不存在待刷入的写入缓存。
修复方案
- 写入前先序列化用户对象,按行拼接后再写入
await append( fakeUsers(faker.datatype.number({ min: 9000, max: 10000 })) .map(user => JSON.stringify(user)) .join('\n') + '\n' );
- 修正读文件逻辑,只处理实际读取到的字节,删除无效的读侧datasync
const readChunk = async (start: number, end: number) => { // 直接分配指定大小的空buffer即可,不需要填充空格 const buffer = Buffer.alloc(end); const fd = await fs.open(filepath, "r"); // 取返回值里的实际读取字节数 const { bytesRead } = await fd.read({ buffer, offset: 0, position: start, length: end }); await fd.close(); // 只截取实际读取到的部分转字符串 return buffer.subarray(0, bytesRead).toString(); };
关于fd.datasync()的疑问解答
- 读侧的
datasync完全无用,可以直接删除,不会产生任何负面影响。 - 写入侧的
datasync是有用的:它会强制把本次写入的内容从操作系统内核缓存刷入物理磁盘,确保append方法返回时数据已经持久化,避免进程意外崩溃导致数据丢失。如果你的业务场景不需要这么强的持久化保证,可以删除该调用提升写入性能;如果需要强一致性,就保留。你之前调用后没解决问题,是因为你的bug和缓存无关,是代码逻辑错误导致的。
内容的提问来源于stack exchange,提问作者karkael
相关产品推荐
相关产品推荐

