简体   繁体   English

第一次读取后,fs.readFile()会将文件内容缓存在服务器的内存中吗?

[英]Will fs.readFile() cache the file's contents in the server's memory after the first read?

I would like to know if the following code would cache the file's contents in the server's memory after reading it once. 我想知道以下代码是否会在读取一次后将文件内容缓存在服务器的内存中。 The reason I ask is because I don't want to have to re read the file every time the user requested the page. 我问的原因是因为每次用户请求页面时我都不想重新读取文件。 I would prefer to have it cached after the first read. 我希望在第一次阅读后缓存它。

fs.exists(fileName, function (exists) {
        if (!exists) {
            console.log("== 404 error");
            resp.writeHead(404, {'Content-Type': 'text/html'});
            resp.end(pageError);
            return;
        }

        fs.readFile(fileName, 'utf8', function (err, data) {
            if (err) {
                resp.writeHead(404, {"Content-Type": "text/html"});
                resp.end(pageError);
                return;
            }

            var contentType = getContentType(req.url);
            var mimeType = mimeTypes[contentType];

            resp.writeHead(200, {"Content-Type": mimeType});
            resp.end(data);
        });
    });

NOTE ** I only want to know how to do this using internal Node JS modules (no express) 注意**我只想知道如何使用内部Node JS模块(没有快递)

You shouldn't use fs.exists() as its deprecated; 你不应该使用fs.exists()作为其弃用; instead, use fs.stat() if you only want to check existence. 相反,如果你只想检查存在,请使用fs.stat() If you are going to open and read a file after checking for existence, then just use fs.readFile() and handle the passed error accordingly for a not existing file. 如果要在检查存在后打开并读取文件,则只需使用fs.readFile()并相应地处理不存在的文件的传递错误。 This is noted within the fs docs for fs.access() but still applies to fs.stat() as well. 这在fs.access()fs文档中fs.access()但仍然适用于fs.stat() Below is the excerpt from the Node.js docs. 以下是Node.js文档的摘录。

Using fs.access() to check for the accessibility of a file before calling fs.open(), fs.readFile() or fs.writeFile() is not recommended. 在调用fs.open()之前,使用fs.access()检查文件的可访问性,不建议使用fs.readFile()或fs.writeFile()。 Doing so introduces a race condition, since other processes may change the file's state between the two calls. 这样做会引入竞争条件,因为其他进程可能会在两次调用之间更改文件的状态。 Instead, user code should open/read/write the file directly and handle the error raised if the file is not accessible. 相反,用户代码应该直接打开/读取/写入文件,并处理在文件无法访问时引发的错误。

fs.readFile() does not do any caching for you, this is something you'll need to create/manage yourself. fs.readFile()不会为您执行任何缓存,这是您自己创建/管理所需的内容。 The below example shows how to create a file cache using a JS Object as a dictionary to keep the file contents indexed by filename. 下面的示例演示如何使用JS Object作为字典创建文件缓存,以保持文件内容索引的文件内容。 Its important to note that you shouldn't be putting gigs of data in the fileCache object, instead this will be good for lots of smaller files. 重要的是要注意你不应该在fileCache对象中放置数据,而是这对许多较小的文件都有好处。

fileCache just needs to be in scope of getFileFromCache() and in a place that won't be garbage collected during runtime. fileCache只需要在getFileFromCache()范围内,并且在运行时不会被垃圾收集的地方。

const fileCache = {}
const getFileFromCache = (filename, cb) => {
    if (fileCache[filename]) {
        return cb(null, fileCache[filename])
    }

    fs.readFile(filename, 'utf8', (err, data) => {
      if (err) {
        return cb(err)
      }

      fileCache[filename] = data
      return cb(null, data)     
    })
}

You could store the file data in a variable, or in a global variable (by using global.<varname> = <filedata> ) if you want to access it across multiple modules. 如果要跨多个模块访问文件数据,可以将文件数据存储在变量或全局变量中(通过使用global.<varname> = <filedata> )。

Of course, as George Cambpell said, anoy modification to the file won't be noticed by your program, since it won't re-read the file. 当然,正如George Cambpell所说,程序不会注意到对文件的修改,因为它不会重新读取文件。

So I would do something like this: 所以我会做这样的事情:

function sendResponse(data) {
    let contentType = getContentType(req.url);
    let mimeType = mimeTypes[contentType];
    resp.writeHead(200, {"Content-Type": mimeType});
    resp.end(data);
}

if(global.fileData) {
    return sendResponse(global.fileData);
}

fs.readFile(fileName, 'utf8', function (err, data) {
    if (err) {
        resp.writeHead(404, {"Content-Type": "text/html"});
        resp.end(pageError);
        return;
    }

    global.fileData = data;
    sendResponse(global.fileData);
});

The first time global.fileData will be empty, so you'll proceed with fs.readfile, store the file content in global.fileData, and send the response. global.fileData第一次为空,因此您将继续使用fs.readfile,将文件内容存储在global.fileData中,然后发送响应。
The second time global.fileData will contain stuff, so you just send the response with that stuff, and you won't read the file again. 第二次global.fileData将包含东西,所以你只需发送带有那些东西的响应,你就不会再次读取该文件了。
For further reference take a look at the official NodeJS documentation: https://nodejs.org/api/globals.html#globals_global 如需进一步参考,请查看官方的NodeJS文档: https//nodejs.org/api/globals.html#globals_global

Another thing you should do is replace fs.exists with fs.access or fs.stat (I usually use fs.access), because the exists method is deprecated. 你应该做的另一件事是用fs.access或fs.stat替换fs.exists(我通常使用fs.access),因为不推荐使用exists方法。
https://nodejs.org/api/fs.html#fs_fs_stat_path_callback https://nodejs.org/api/fs.html#fs_fs_stat_path_callback
https://nodejs.org/api/fs.html#fs_fs_access_path_mode_callback https://nodejs.org/api/fs.html#fs_fs_access_path_mode_callback

Happy coding! 快乐的编码!

Will fs.readFile() cache the file's contents in the server's memory after the first read? 第一次读取后,fs.readFile()会将文件内容缓存在服务器的内存中吗?

No. fs.readFile() itself does no caching. fs.readFile()本身没有缓存。

But, the underlying operating system will do file caching and as long as there isn't so much other file activity going on that the cached read gets flushed, then the OS will probably fetch the file from a local memory cache the 2nd, 3rd times you read it. 但是,底层操作系统将执行文件缓存,只要没有那么多其他文件活动继续刷新缓存读取,那么操作系统可能会从本地内存缓存中获取第二次,第三次你看了。

If you want to assure the caching yourself, then you should just store the contents yourself once you first read it and from then on, you can just use the previously read contents. 如果您想确保自己进行缓存,那么您应该在第一次阅读后自己存储内容,然后再使用以前阅读的内容。

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

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