繁体   English   中英

node.js fs - 流文件“向后” - 从下到上

[英]node.js fs - stream file “backwards” - from bottom to top

使用Node.js,将文件从文件系统流式传输到Node.js的最佳方法是什么,但是从底部到顶部向后读取它? 我有一个大文件,如果我只想要最后10行,从顶部读取似乎没有多大意义。 这可能吗?

现在我有这个可怕的代码,我们用浏览器执行GET请求来查看服务器日志,并传递一个查询字符串参数来告诉服务器我们想要读取的日志文件末尾有多少行:

function get(req, res, next) {

    var numOfLinesToRespondWith = req.query.num_lines || 10;

    var fileStream = fs.createReadStream(stderr_path, {encoding: 'utf8'});

    var jsonData = [];   //where jsonData gets populated
    var ret = [];

    fileStream.on('data', function processLineOfFileData(chunk) {
        jsonData.push(String(chunk));
    })
    .on('end', function handleEndOfFileData(err) {
        if (err) {
            log.error(colors.bgRed(err));
            res.status(500).send({"error reading from smartconnect_stdout_log": err.toString()});
        }
        else {

         for(var i = 0; i < numOfLinesToRespondWith; i++){
                ret.push(jsonData.pop());
           }

          res.status(200).send({"smartconnect_stdout_log": ret});

        }
    });
}

上面的代码读取整个文件,然后在读取整个文件后将请求的行数添加到响应中。 这很糟糕,有更好的方法吗? 任何建议都会很乐意得到满足。

(上面代码的一个问题是它写出了日志的最后几行,但是行的顺序是相反的......)

一种可行的方法是:

process.exec('tail -r ' + file_path).pipe(process.stdout);

但是这个语法是不正确的 - 所以我的问题就是 - 如何将该命令的结果传递到Node.js中的数组并最终传输到JSON HTTP响应中?

我创建了一个名为fs-backwards-stream的模块,可以满足您的需求。 https://www.npmjs.com/package/fs-backwards-stream

如果您需要通过行而不是字节块解析的结果,则应使用模块fs-reverse https://www.npmjs.com/package/fs-reverse

这两个模块流都可以简单地读取文件的最后n个字节。

这是一个使用普通节点fs apis并且没有依赖关系的示例。

https://gist.github.com/soldair/f250fb497ce592c3694a

希望有所帮助。

如果你在Linux计算机上,一种简单的方法是在节点中执行tac命令作为process.exec("tac yourfile.dat")并将其传递给你的写入流

您也可以使用切片文件 ,然后自己反转订单。

另外,看看@alexmills在评论中所说的内容

这是我现在得到的最佳答案

Mac / UNIX上的tail命令从末尾读取文件并将管道读取到stdout(如果这是松散的语言,请更正我)

    var cp = require('child_process');

    module.exports =  function get(req, res, next) {

        var numOfLinesToRespondWith = req.query.num_lines || 100;

        cp.exec('tail -n 5 ' + stderr_path, function(err,stdout,stderr){

            if(err){
                log.error(colors.bgRed(err));
                res.status(500).send({"error reading from smartconnect_stderr_log": err.toString()});
            }
            else{
                var data = String(stdout).split('\n');
                res.status(200).send({"stderr_log": data});
            }
        });
    }

这似乎工作得很好 - 然而,它确实在单独的进程上运行,这个进程本身很昂贵,但可能比读取整个10,000行日志文件更好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM