You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS中读取流式写入文件的缓冲问题排查

文件先写后读时读取内容为空的原因与解决办法

问题现象

对同一文件执行先写入再读取操作,代码运行后testfile.txt已正确写入磁盘,但readTextFile输出[''],表现为文件为空。将写入逻辑改为同步方式后,代码可正常工作。

原代码

const fs = require("fs");
const FileA = 'testfile.txt';

const createTextFile = async () => {
   const rows = ['a','b','c','d'];
   const outstream = fs.createWriteStream(FileA, {flush: true, autoClose: true});
   for(el of rows){
      outstream.write(el+'\n');
   }
   outstream.end();
};

const readTextFile = () => {
   const clist = fs.readFileSync(FileA).toString().split("\n");
   console.log(clist);
};

const flow = async config => {
   await createTextFile();
   readTextFile();
};

flow();

原因分析

  • 虽然createTextFile标记为async,但函数内部没有等待流异步操作完成的逻辑。outstream.end()仅触发流的结束流程,不会阻塞等待数据真正刷入磁盘并关闭流。await createTextFile()实际上会立即执行完毕,导致readTextFile在流还未完成磁盘持久化时就执行,因此读取到空内容。
  • fs.createWriteStream的flush: true选项仅控制单次write后尝试刷新缓存,但流的finish事件(表示所有数据已写入磁盘)仍为异步触发,不会同步阻塞函数执行。

解决方案

方案1:将流操作包装为Promise

通过监听流的finish事件,确保数据完全写入磁盘后再resolve Promise,让await能正确等待写入完成:

const fs = require("fs");
const FileA = 'testfile.txt';

const createTextFile = async () => {
  return new Promise((resolve, reject) => {
    const rows = ['a','b','c','d'];
    const outstream = fs.createWriteStream(FileA, { autoClose: true });
    
    // 监听流完成事件
    outstream.on('finish', resolve);
    // 处理流错误
    outstream.on('error', reject);
    
    for(const el of rows){
      outstream.write(el+'\n');
    }
    outstream.end();
  });
};

const readTextFile = () => {
   const clist = fs.readFileSync(FileA).toString().split("\n");
   console.log(clist);
};

const flow = async config => {
   await createTextFile();
   readTextFile();
};

flow();

方案2:使用同步写入API(简单直接)

如果不需要异步流的优势,直接使用同步写入API,确保数据完全写入磁盘后再执行后续读取:

const fs = require("fs");
const FileA = 'testfile.txt';

const createTextFile = () => {
  const rows = ['a','b','c','d'];
  // 同步写入内容
  fs.writeFileSync(FileA, rows.join('\n') + '\n');
};

const readTextFile = () => {
   const clist = fs.readFileSync(FileA).toString().split("\n");
   console.log(clist);
};

const flow = async config => {
   createTextFile();
   readTextFile();
};

flow();

内容的提问来源于stack exchange,提问作者Lowell Boone

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.19 17:24:54