Nodejs 使用fs.readFile高频读取和fs.writeFile高频写入时,出现问题

Nodejs 使用fs.readFile高频读取和fs.writeFile高频写入时,出现问题

我是建一个索引文件,用来做好友的模糊查询。但是在批量写入索引文件的时候,就会出现各种问题。 例如

    undefined:945
    })
    ^
    SyntaxError: Unexpected token }
        at Object.Function (<anonymous>)
        at /Volumes/macFile/nodeProject/cngouwo/routes/api/addFriend.js:21:23
        at fs.js:266:14
        at Object.oncomplete (fs.js:107:15)
    
    Process finished with exit code 8

不仅仅这一个错误。各种各样的错误。

不知道为何如此?

代码奉上:

    var fs = require('fs'),
        util = require('util');
module.exports = function(req,res){
    var id = req.body.id,
        name = req.body.name,
        friend = {};

    fs.readFile('out.txt',function(err,data){
        if(err){
            var _collection = friend.collection = {},
                _index = friend.index = {};
        }
        else{
            var friends = data.toString();
            friend = (new Function("return "+friends))();
            var _collection = friend.collection,
                _index = friend.index;
        }
        _collection['id_'+id] = name;
        for(var x = 0 ; x &lt; name.length ; x++){
            if(!_index[name[x]])
                _index[name[x]] = {};

            if(!_index[name[x]]['id_'+id]){
                _index[name[x]]['id_'+id] = {};
                _index[name[x]]['id_'+id]['s'] = 1;
                _index[name[x]]['id_'+id]['i'] = [x];
            }else{
                _index[name[x]]['id_'+id]['s'] += 1;
                _index[name[x]]['id_'+id]['i'].push(x);
            }
        };
        var json = util.inspect(friend,false,4);
        fs.writeFile("out.txt", json, function(err) {
            friend = null;
            json = null;
            if(err){
                res.send('失败')
            }else{
                res.send({ms:'cd'})
            }
        });
    });
}


9 回复

当使用 fs.readFilefs.writeFile 高频读取和写入文件时,可能会遇到多种问题,比如数据竞争、内存泄漏、性能瓶颈等。以下是一些可能的原因及解决方案:

问题分析

  1. 数据竞争:由于 fs.readFile 是异步操作,在频繁调用时,可能会导致文件状态不一致或数据混乱。
  2. 内存泄漏:频繁地创建临时变量和对象,可能会导致内存泄漏。
  3. 性能瓶颈:频繁的 I/O 操作会阻塞事件循环,导致 Node.js 应用性能下降。

示例代码优化

为了减少这些问题,可以考虑以下优化措施:

  1. 合并写入操作:将多次写入合并为一次写入,减少 I/O 操作。
  2. 使用流:使用 fs.createWriteStreamfs.createReadStream 来处理大量数据。
  3. 避免重复读取:缓存已读取的数据,而不是每次都从文件中读取。

示例代码

var fs = require('fs');
var util = require('util');

let cachedData = {};

module.exports = function(req, res) {
    const id = req.body.id;
    const name = req.body.name;

    // 读取缓存中的数据,如果没有则从文件中读取
    if (!cachedData.data) {
        fs.readFile('out.txt', 'utf-8', (err, data) => {
            if (err) {
                cachedData.data = {};
            } else {
                cachedData.data = JSON.parse(data);
            }

            updateCache(id, name);
            writeToFile();
        });
    } else {
        updateCache(id, name);
        writeToFile();
    }
};

function updateCache(id, name) {
    const friend = cachedData.data;
    friend.collection = friend.collection || {};
    friend.index = friend.index || {};

    friend.collection['id_' + id] = name;

    for (let i = 0; i < name.length; i++) {
        const char = name[i];
        if (!friend.index[char]) {
            friend.index[char] = {};
        }

        if (!friend.index[char]['id_' + id]) {
            friend.index[char]['id_' + id] = { s: 1, i: [i] };
        } else {
            friend.index[char]['id_' + id].s += 1;
            friend.index[char]['id_' + id].i.push(i);
        }
    }
}

function writeToFile() {
    const jsonData = JSON.stringify(cachedData.data, null, 2);
    fs.writeFile('out.txt', jsonData, (err) => {
        if (err) {
            res.send('失败');
        } else {
            res.send({ ms: 'cd' });
        }
    });
}

解释

  1. 缓存数据:使用 cachedData 对象来缓存已读取的数据,减少文件读取次数。
  2. 更新缓存:每次请求时,更新缓存中的数据。
  3. 合并写入:将所有更新操作完成后,一次性写入文件,减少 I/O 操作。

通过这些优化,可以显著减少高频读写带来的问题,并提高应用的整体性能。


求大神帮助

顺便说一下,报错服务终止后,重新启动服务,从报错的数据继续写,就又可以跑。。

friend = (new Function("return "+friends))();

这句出现的问题吧?

这个应该是数据还没写完你又继续读, writeFile的时候应该没有锁住文件读的, 你可能才写了一半就开始读了!

在回调里面写的writeFile,应该是在readFile结束后才开始write的吧。

friend = (new Function("return "+friends))();

这句好费解。什么意思啊 为什么这样用

没有什么费解的啊 new Function方法可以定义一个function(function body接受字符串), 具体请看文档…

在使用 Node.js 的 fs.readFilefs.writeFile 进行高频读写操作时,可能会遇到一些常见的问题,比如文件竞争、内存泄漏、性能瓶颈等。以下是一些可能的原因及改进建议:

原因分析

  1. 文件竞争:频繁的读写操作可能导致文件系统竞争,尤其是在多进程或分布式环境中。
  2. 同步问题:使用 fs.readFilefs.writeFile 时,如果操作没有正确处理异步回调,可能会导致数据丢失或不一致。
  3. 内存泄漏:频繁地创建和销毁对象,如果不进行适当的清理,可能导致内存泄漏。

示例改进代码

var fs = require('fs');
var util = require('util');

module.exports = function(req, res) {
    var id = req.body.id;
    var name = req.body.name;

    fs.readFile('out.txt', 'utf8', function(err, data) {
        if (err && err.code !== 'ENOENT') { // 文件不存在时忽略错误
            return res.status(500).send('读取文件时出错');
        }

        let friend = data ? JSON.parse(data) : { collection: {}, index: {} };

        friend.collection['id_' + id] = name;
        for (let i = 0; i < name.length; i++) {
            if (!friend.index[name[i]]) {
                friend.index[name[i]] = {};
            }
            if (!friend.index[name[i]]['id_' + id]) {
                friend.index[name[i]]['id_' + id] = {
                    s: 1,
                    i: [i]
                };
            } else {
                friend.index[name[i]]['id_' + id].s += 1;
                friend.index[name[i]]['id_' + id].i.push(i);
            }
        }

        fs.writeFile('out.txt', JSON.stringify(friend), 'utf8', function(err) {
            if (err) {
                return res.status(500).send('写入文件时出错');
            }
            res.send({ ms: 'cd' });
        });
    });
};

解释

  1. 文件读取:使用 fs.readFile 读取文件,并指定编码为 utf8,避免后续转换。
  2. 错误处理:检查 err 并确保只在实际错误发生时处理它,而不是忽略所有错误。
  3. JSON 操作:将读取的数据解析为 JSON 对象,而不是使用 new Function,这可以避免潜在的安全问题。
  4. 写入文件:使用 fs.writeFile 将更新后的 JSON 数据写回文件,同样指定编码为 utf8

通过这些改进,可以提高代码的健壮性和可维护性,减少高频读写操作带来的问题。

回到顶部