Node.js使用Transform流传输对象数组写入文件报错排查
错误原因
这个类型错误的核心是流传输的数据类型和下游要求不匹配:
- Node.js的文件可写流(
fs.createWriteStream创建的流)默认只接受字符串、Buffer、Uint8Array类型的数据,无法直接写入JS对象。 - 你代码里的
new Buffer(obj2)写法是无效的:Buffer构造函数不支持直接接收普通JS对象,传入后只会生成内容为[object Object]的无效Buffer,本质上你还是在尝试向下游传递对象类型数据。 - 你提到的
objectMode: true配置只是让流支持传递JS对象,不代表非对象模式的文件流可以接收对象,而且你大概率没有给所有处理对象的流节点正确配置该参数,也没有做对象到可写入文本/二进制的转换。
修复方法
你需要在管道中增加一步格式转换:所有处理对象的流节点开启对象模式,在写入文件前,把处理完成的JS对象转换成文件流支持的字符串/Buffer格式。
修正后的可运行代码如下:
const stream = require('stream'); const fs = require('fs'); const util = require('util'); const { pipeline } = require('stream/promises'); // 此处替换为你的实际数据源 const res = [ { id: 1, name: 'demo', inner: [{ val: 'a' }, { val: 'b' }] } ]; // 从对象数组创建可读流,默认自动开启对象模式 const readStream = stream.Readable.from(res); // 自定义展开转换流 function Flatten(options) { // 显式开启对象模式,支持接收、输出JS对象 stream.Transform.call(this, { ...options, objectMode: true }); } util.inherits(Flatten, stream.Transform); Flatten.prototype._transform = function (chunk, enc, cb) { const sourceObj = chunk; // 增加边界判断,避免inner不存在时遍历报错 if (!Array.isArray(sourceObj.inner)) { return cb(); } for (let j = 0; j < sourceObj.inner.length; j++) { const merged = { ...sourceObj, ...sourceObj.inner[j] }; delete merged.inner; // 直接推送处理完成的对象,不要用Buffer包裹对象 this.push(merged); } cb(); }; // 新增格式转换流:将JS对象转为文件可写入的字符串 const objectToStringStream = new stream.Transform({ objectMode: true, // 接收上游传递的对象 transform(chunk, enc, cb) { // 此处可根据你的需求调整输出格式: // 存JSON行格式就用JSON.stringify加换行,存CSV就拼接CSV行字符串 const outputLine = JSON.stringify(chunk) + '\n'; cb(null, outputLine); } }); const flattenTransform = new Flatten(); const writeStream = fs.createWriteStream('test1.txt'); // 按顺序串联管道:读流 -> 对象展开 -> 格式转字符串 -> 写文件 await pipeline(readStream, flattenTransform, objectToStringStream, writeStream);
注意事项
- 废弃的
new Buffer()写法不要再用,当前Node.js版本创建Buffer请使用Buffer.from(),且该方法同样不支持直接传入普通对象,必须传入字符串、字节数组、Buffer实例等合法参数。 - 如果你需要输出CSV、自定义文本等其他格式,只需要修改
objectToStringStream中的转换逻辑,将对象拼接为对应格式的字符串即可。 - 对象模式仅在需要传递JS对象的流节点上开启即可,最后对接文件流的节点输出必须是字符串/Buffer类型,文件流本身不需要开启对象模式。
内容的提问来源于stack exchange,提问作者KuldeepJadhav
相关产品推荐
相关产品推荐

