在不下载整个文件的情况下读取和解析 S3 中的 CSV 文件
Read and parse CSV file in S3 without downloading the entire file
使用 node.js,目的是 运行 此模块作为 AWS Lambda 函数。
使用 aws-sdk
中的 s3.getObject()
,我能够成功地从 Amazon S3 中获取一个非常大的 CSV 文件。目的是读取文件中的每一行并在每一行的正文中发出一个事件。
在我能找到的所有示例中,看起来 S3 中的整个 CSV 文件都必须进行缓冲或流式处理,转换为字符串,然后逐行读取。
s3.getObject(params, function(err, data) {
var body = data.Body.toString('utf-8');
}
鉴于源 CSV 文件的大小,此操作需要很长时间。此外,CSV 行的长度各不相同,我不确定是否可以使用缓冲区大小作为选项。
问题
有没有办法逐行提取 node.js 和 read/transform 中的 S3 文件,从而避免首先在内存中对整个文件进行字符串化?
理想情况下,我更愿意使用 fast-csv
and/or node-csv
的更好功能,而不是手动循环。
您应该能够使用 createReadStream
method 并将其通过管道传输到 fast-csv:
const s3Stream = s3.getObject(params).createReadStream()
require('fast-csv').fromStream(s3Stream)
.on('data', (data) => {
// do something here
})
不是逐行,但您可以使用 Range
header 按字节范围获取 S3 objects。因此,您可以一次读取 1000 个字节,并在读取数据时管理您这一端的新行。查看 GET Object documentation 并搜索范围 header.
我没有足够的声誉来发表评论,但截至目前 'fast-csv' 不存在接受的答案方法“fromStream”。现在您需要使用 parseStream 方法:
const s3Stream = s3.getObject(params).createReadStream()
require('fast-csv').parseStream(s3Stream)
.on('data', (data) => {
// use rows
})
对我来说,解决我问题的答案是,
const csv = require('@fast-csv/parse');
const params = {
Bucket: srcBucket,
Key: srcKey,
};
const csvFile = s3.getObject(params).createReadStream();
let parserFcn = new Promise((resolve, reject) => {
const parser = csv
.parseStream(csvFile, { headers: true })
.on("data", function (data) {
console.log('Data parsed: ', data);
})
.on("end", function () {
resolve("csv parse process finished");
})
.on("error", function () {
reject("csv parse process failed");
});
});
try {
await parserFcn;
} catch (error) {
console.log("Get Error: ", error);
}
使用 node.js,目的是 运行 此模块作为 AWS Lambda 函数。
使用 aws-sdk
中的 s3.getObject()
,我能够成功地从 Amazon S3 中获取一个非常大的 CSV 文件。目的是读取文件中的每一行并在每一行的正文中发出一个事件。
在我能找到的所有示例中,看起来 S3 中的整个 CSV 文件都必须进行缓冲或流式处理,转换为字符串,然后逐行读取。
s3.getObject(params, function(err, data) {
var body = data.Body.toString('utf-8');
}
鉴于源 CSV 文件的大小,此操作需要很长时间。此外,CSV 行的长度各不相同,我不确定是否可以使用缓冲区大小作为选项。
问题
有没有办法逐行提取 node.js 和 read/transform 中的 S3 文件,从而避免首先在内存中对整个文件进行字符串化?
理想情况下,我更愿意使用 fast-csv
and/or node-csv
的更好功能,而不是手动循环。
您应该能够使用 createReadStream
method 并将其通过管道传输到 fast-csv:
const s3Stream = s3.getObject(params).createReadStream()
require('fast-csv').fromStream(s3Stream)
.on('data', (data) => {
// do something here
})
不是逐行,但您可以使用 Range
header 按字节范围获取 S3 objects。因此,您可以一次读取 1000 个字节,并在读取数据时管理您这一端的新行。查看 GET Object documentation 并搜索范围 header.
我没有足够的声誉来发表评论,但截至目前 'fast-csv' 不存在接受的答案方法“fromStream”。现在您需要使用 parseStream 方法:
const s3Stream = s3.getObject(params).createReadStream()
require('fast-csv').parseStream(s3Stream)
.on('data', (data) => {
// use rows
})
对我来说,解决我问题的答案是,
const csv = require('@fast-csv/parse');
const params = {
Bucket: srcBucket,
Key: srcKey,
};
const csvFile = s3.getObject(params).createReadStream();
let parserFcn = new Promise((resolve, reject) => {
const parser = csv
.parseStream(csvFile, { headers: true })
.on("data", function (data) {
console.log('Data parsed: ', data);
})
.on("end", function () {
resolve("csv parse process finished");
})
.on("error", function () {
reject("csv parse process failed");
});
});
try {
await parserFcn;
} catch (error) {
console.log("Get Error: ", error);
}