使用Node.js读取文本文件?


Answers:


172

您将要使用process.argv数组访问命令行参数以获取文件名,并使用FileSystem模块(fs)来读取文件。例如:

// Make sure we got a filename on the command line.
if (process.argv.length < 3) {
  console.log('Usage: node ' + process.argv[1] + ' FILENAME');
  process.exit(1);
}
// Read the file and print its contents.
var fs = require('fs')
  , filename = process.argv[2];
fs.readFile(filename, 'utf8', function(err, data) {
  if (err) throw err;
  console.log('OK: ' + filename);
  console.log(data)
});

为了稍微分解一下,process.argv通常长度为2,第零个是“节点”解释器,第一个是节点当前正在运行的脚本,其后的项目在命令行中传递。从argv中提取文件名后,就可以使用文件系统函数读取文件并对其内容进行任何操作。用法示例如下所示:

$ node ./cat.js file.txt
OK: file.txt
This is file.txt!

[编辑]正如@wtfcoder所提到的那样,使用“ fs.readFile()”方法可能不是最好的主意,因为它会在将文件的全部内容提供给回调函数之前对其进行缓冲。这种缓冲可能潜在地使用大量内存,但是更重要的是,它没有利用node.js的核心功能之一-异步事件I / O。

处理大文件(或任何文件,实际上)的“节点”方法是使用fs.read()和处理每个可用的块,因为它们可从操作系统获得。但是,以这种方式读取文件需要您自己(可能)对文件进行增量解析/处理,并且一定数量的缓冲可能是不可避免的。


太好了,非常感谢,非常有帮助。我如何按行拆分此数据?
花式的2012年

10
@fancy:try var lines = data.split(/\r?\n/);,那么数组“ lines”将具有每一行。
maerics

1
如果文本文件很大,这不是一个好主意,因为它将全部读取到内存中,如果在fs.createFilestream中处理一个1000mb的CSV文件,则需要注意行拆分,尽管作为数据块不会(在大多数情况下)落在边界线(有些人已经想出了解决方案-谷歌)
马特·弗里曼

1
@wtfcoder:是的,非常重要。我的意图只是演示读取命令行上命名的文件的简单情况。显然,有许多微妙之处(尤其是性能)超出了此问题的范围。
maerics'2

我发布了一个类似问题的解决方案,用于使用流同步地解析非常大的文件。见:stackoverflow.com/questions/16010915/...
杰拉德

35

用节点Usign fs。

var fs = require('fs');

try {  
    var data = fs.readFileSync('file.txt', 'utf8');
    console.log(data.toString());    
} catch(e) {
    console.log('Error:', e.stack);
}

请注意,这是同步版本。
Rich Werden

@RichWerden在这种情况下,“同步”是什么意思?
杰森

1
在Node中,当某些事情是“同步的”时,它将停止/阻止系统执行其他任何操作。假设您有一个节点Web服务器-如果在发生上述情况时出现其他任何请求,则该服务器将不会/无法响应,因为它正忙于读取文件。
Rich Werden

27

恕我直言,fs.readFile()应该避免,因为它会将所有文件加载到内存中,并且在读取完所有文件之前不会调用回调。

读取文本文件最简单的方法是逐行读取它。我建议使用BufferedReader

new BufferedReader ("file", { encoding: "utf8" })
    .on ("error", function (error){
        console.log ("error: " + error);
    })
    .on ("line", function (line){
        console.log ("line: " + line);
    })
    .on ("end", function (){
        console.log ("EOF");
    })
    .read ();

对于.properties或json文件等复杂的数据结构,您需要使用解析器(内部还应使用缓冲读取器)。


7
感谢您指出这项技术。您是对的,这也许是最好的方法,但是我只是认为,在这个问题的上下文中,这有点令人困惑,我认为这是在问一个不需要的用例。如上所述,如果只是传递给命令行工具的小文件,则没有理由不使用fs.readFile()fs.readFileSync()。它必须是一个巨大的文件才能引起明显的等待。喜欢的package.json一个JSON配置文件很可能是在1 KB,所以你可以fs.readFile()JSON.parse()它。
John Starr Dewar

1
BufferedReader可能已更改其签名。我必须用BufferedReader,DataReader替换BufferedReader,其中BufferedReader是模块。见github.com/Gagle/Node-BufferedReader
bnieland '16

13
我看到BufferedReader现在已被弃用。
马克·罗奇金德

6

您可以使用readstream和pipe逐行读取文件,而无需一次将所有文件读入内存。

var fs = require('fs'),
    es = require('event-stream'),
    os = require('os');

var s = fs.createReadStream(path)
    .pipe(es.split())
    .pipe(es.mapSync(function(line) {
        //pause the readstream
        s.pause();
        console.log("line:", line);
        s.resume();
    })
    .on('error', function(err) {
        console.log('Error:', err);
    })
    .on('end', function() {
        console.log('Finish reading.');
    })
);

5

我正在发布一个完整的示例,我终于开始工作了。在这里,我正在rooms/rooms.txt从脚本中读取文件rooms/rooms.js

var fs = require('fs');
var path = require('path');
var readStream = fs.createReadStream(path.join(__dirname, '../rooms') + '/rooms.txt', 'utf8');
let data = ''
readStream.on('data', function(chunk) {
    data += chunk;
}).on('end', function() {
    console.log(data);
});
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.