javascript - 发出在循环中写入文件并从临时目录中读取的问题
问题描述
我正在尝试从 API 下载报告,但发送回数据的方式是使用一个压缩文件夹,其中包含另一个文件夹,并且该文件夹中有十几个压缩 JSON 文件。为了清楚起见,它看起来像这样:
report.zip/
├── reportID/ <- this is a regular folder
│ ├── reportID_123.json.gz
│ ├── reportID_456.json.gz
│ ├── reportID_789.json.gz
│ └── reportID_159.json.gz
我正在尝试解压缩第一个文件夹,然后解压缩每个单独的文件,最后循环并读取每个 JSON 文件的内容并将它们添加到单个对象中。但我有两个问题。
第一个是,虽然此代码的第一部分在解压缩第一个文件夹并提取每个 JSON 文件的名称时有效,而第二部分在解压缩它们时有效,但每个解压缩的文件都与之前的文件完全相同(这不是t 手动完成整个操作时的情况)。
var zip = new AdmZip(tempFilePath);
var zipEntries = zip.getEntries(); // an array of ZipEntry records
const allZips = [];
const tempOutputPath = path.join(os.tmpdir(), 'output');
zip.extractAllTo(/*target path*/tempOutputPath, /*overwrite*/true);
zipEntries.forEach(function(zipEntry) {
allZips.push(zipEntry.entryName);
});
console.log (allZips);
const allData = [];
for (var i = 0; i <= allZips.length; i++) {
const zippedFileName = path.join(tempOutputPath, allZips[i]);
const finalOutputName = path.join(tempOutputPath, allZips[i].replace('.gz', ''));
console.log(zippedFileName);
const inp = fs.createReadStream(zippedFileName);
const out = fs.createWriteStream(finalOutputName);
inp.pipe(unzip).pipe(out);
console.log('File piped successfully');
console.log(finalOutputName);
let rawData = fs.readFileSync(finalOutputName);
let data = rawData.toString();
console.log(data);
allData.push(data);
}
第二个问题是,即使在循环时,它也只能从某些文件中实际提取数据,这似乎是随机的,因为代码和文件除了名称之外都是相同的。这可能与循环结束后,我得到以下错误有关,尽管循环结束也是我的代码的结束:
(node:15772) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 end listeners added. Use emitter.setMaxListeners() to increase limit
(node:15772) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 unpipe listeners added. Use emitter.setMaxListeners() to increase limit
(node:15772) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 drain listeners added. Use emitter.setMaxListeners() to increase limit
(node:15772) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 error listeners added. Use emitter.setMaxListeners() to increase limit
(node:15772) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 close listeners added. Use emitter.setMaxListeners() to increase limit
(node:15772) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 finish listeners added. Use emitter.setMaxListeners() to increase limit
(node:15772) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 data listeners added. Use emitter.setMaxListeners() to increase limit
(node:15772) UnhandledPromiseRejectionWarning: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received type undefined
最后一件事,如果它是相关的,当硬编码文件名而不是使用临时文件路径时,这一切似乎工作得更好(尽管仍然不完美)。不幸的是,我必须使用临时文件路径,因为这是一个不允许常规路径的云函数。
解决方案
.pipe()
是异步的。所以,这行代码:
inp.pipe(unzip).pipe(out);
在未来某个未知的时间结束。因此,您正在尝试使用以下内容读取输出文件:
fs.readFileSync(finalOutputName);
在您知道输出已经完成之前。如果您要为此使用流,那么您需要观察close
writestream 上的事件,这样您就可以知道它.pipe()
已完全完成。您还应该注意error
流上的事件以实施正确的错误处理。
在为事件实现一个监听器close
以读取输出之后,按照您的代码编写方式,您必须等待所有流都获得它们的close
事件才能使用allData
,因为只有这样它才会包含所有数据。
在试图了解您的代码流程以提出替代方案时,我看到了这行代码:
inp.pipe(unzip).pipe(out);
但是,没有变量的定义unzip
。
此外,除了创建所有临时文件之外,了解这段代码的最终目标是有帮助的,因此我们或许可以提出更好的方法。
作为一个小的简化,您可以替换它:
const allZips = [];
zipEntries.forEach(function(zipEntry) {
allZips.push(zipEntry.entryName);
});
有了这个:
const allZips = zipEntries.map(zipeEntry => zipEntry.entryName);
当我试图更好地理解这段代码时,您似乎正在尝试对您的两个流进行处理,而您.pipe()
是将提取的文件复制到新位置。fs.copyFile()
使用or可以更简单地做到这一点fs.copyFileSync()
。
推荐阅读
- php - 以下哪一项是从 PHP 类中的函数获取值的最佳实践?
- sql-server - SSIS 数据类型转换问题
- typescript - 如何在打字稿中定义函数类型,其变量参数名称仅限于某些接口的键
- javascript - div 元素的屏幕截图并发送到 aws s3 存储
- python - 强制子进程使用 Python 3
- uwp - 如何将 IntPtr 从 C# 传递到 C++
- sql-server - 是否可以在唯一约束中忽略 null?
- python - 使用 Python / Pandas 从大型 csv 文件获取相关矩阵的问题
- python - Jupyter notebook 空闲锁定红移表
- openid - 将我自己的外部身份提供者添加到 Keycloak 会产生“来自令牌的错误受众”。