使用Node读取最新的csv记录

时间:2014-07-07 20:40:28

标签: node.js csv

我希望观看CSV文件,并在更改后获取最新记录。我运行以下shell命令来构建一个非常简单的csv文件并每秒追加一个新行:

rm test.csv & x=0 && while true; do echo "${x},${x},${x}" >> test.csv; x=$(($x+1)); sleep 1; done

以下代码打印文件的所有记录,直到第一次更改,然后只是发出虚线,就像它没有重新读取文件一样:

'use strict';

var fs = require('fs'),
    dataFile = __dirname + '/server/data/test.csv',
    csv = require('csv');

var parser = csv.parse({delimiter: ','}, function(err, data){
    console.log(data);
});

var watcher = fs.watch(dataFile);
watcher.on('change', fileChange);

function fileChange(e, fn){
    if (e) console.error(e)

    fs.createReadStream(dataFile).pipe(parser);
    console.log('-------')
}

fileChange函数不应该在每次更改时重新读取文件吗?我在这里的最终计划是同时获取前一行和当前行,并使用lodash的difference函数仅返回差异。如果有更好的方法,我可以听听它。

2 个答案:

答案 0 :(得分:0)

我的猜测是fs.createReadStream()已打开文件且未关闭。所以在第二个事件fs.createReadStream()失败了。没有bueno。

尝试使用fs.readFile()代替:

function fileChange(e, fn){
    if (e) console.error(e)

    fs.readFile(dataFile, function (err, data) {
        if (err) throw err;
        console.log(data);
        console.log('-------')
    });
};

请参阅此处的文档:http://nodejs.org/api/fs.html#fs_fs_readfile_filename_options_callback

答案 1 :(得分:0)

我最后通过声明更改文件并读取流数据的大小差异来解决问题:

'use strict';

var fs = require('fs'),
    dataFile = __dirname + '/server/data/test.csv',
    readSize = 0,
    csv = require('csv');

var parser = csv.parse();
parser.on('readable', function(data){
    var record;
    while(record = parser.read()){
        console.log(record);
    }
});

var watcher = fs.watch(dataFile);
watcher.on('change', fileChange);

// fires when the watched file changes
function fileChange(e, fn){

    // get these syncronously
    var stats = fs.statSync(dataFile);
    // if it's smaller, wait half a second
    if (stats.size <= readSize) {
        setTimeout(fileChange, 500);
    }
    // read the stream offset 
    var stream = fs.createReadStream(dataFile, {start: readSize, end: stats.size});

    stream.on('data', function(chunk){
        parser.write(chunk.toString());
    });

    readSize = stats.size;
}

对于为什么这可能不起作用的任何反馈将不胜感激。