Прочитать текстовый файл с помощью Node.js?

124

Мне нужно передать текстовый файл в терминал, а затем прочитать из него данные, как я могу это сделать?

node server.js file.txt

Как мне пройти путь от терминала, как мне прочитать это на другой стороне?

маскарадный
источник
Если вы обнаружите, что добавляете дополнительные параметры в командную строку, вы можете использовать Optimist .
Джесс
stackoverflow.com/questions/6156501/… показывает другой способ чтения текстового файла
Марк

Ответы:

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обычно будет длина два, нулевой элемент - это интерпретатор «узла», а первый - это сценарий, который в настоящее время выполняется узлом, элементы после этого передавались в командной строке. Как только вы вытащили имя файла из argv, вы можете использовать функции файловой системы для чтения файла и делать с его содержимым все, что захотите. Пример использования будет выглядеть так:

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

[Edit] Как упоминает @wtfcoder, использование fs.readFile()метода " " может быть не лучшей идеей, потому что он буферизует все содержимое файла перед передачей его функции обратного вызова. Эта буферизация потенциально может использовать много памяти, но, что более важно, она не использует одну из основных функций node.js - асинхронный, равномерный ввод-вывод.

"Узловой" способ обработки большого файла (или любого другого файла на самом деле) будет заключаться в использовании fs.read()и обработке каждого доступного фрагмента, поскольку он доступен из операционной системы. Однако чтение файла как такового требует от вас выполнения собственного (возможно) инкрементного синтаксического анализа / обработки файла, и некоторое количество буферизации может оказаться неизбежным.

maerics
источник
Замечательно, большое спасибо, очень полезно. Как я мог разбить эти данные по строкам?
fancy
10
@fancy: попробуйте var lines = data.split(/\r?\n/);, тогда в массиве "строк" будет каждая строка.
maerics
1
Это не лучшая идея, если текстовый файл большой, так как он все будет считан в память, если вы обработаете, скажем, CSV-файл размером 1000 МБ, посмотрите на fs.createFilestream, вам нужно будет позаботиться о разделении строк, хотя как фрагменты данных (в большинстве случаев) не попадает в границы линии (некоторые люди уже придумали решения - Google)
Матт Фреман
1
@wtfcoder: да, очень хорошая мысль. Мое намерение состояло в том, чтобы просто продемонстрировать простой случай чтения файла, указанного в командной строке; очевидно, что есть много тонкостей (особенно производительность), которые выходят за рамки этого вопроса.
maerics
Я опубликовал решение аналогичного вопроса по синтаксическому разбору очень большого файла, используя поток, синхронный. см .: stackoverflow.com/questions/16010915/…
Джерард
35

Используйте fs с node.

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, что вы подразумеваете под «синхронным» в этом контексте?
Json
1
В Node, когда что-то «синхронно», оно останавливает / блокирует работу системы. Предположим, у вас есть веб-сервер узла - если во время вышеупомянутого процесса поступают какие-либо другие запросы, сервер не будет / не сможет ответить, потому что он занят чтением файла.
Rich Werden
27

IMHO, 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(). Это должен быть огромный файл, чтобы вызвать заметное ожидание. Файл конфигурации JSON, такой как package.json, скорее всего, будет меньше 1 КБ, так что вы можете просто fs.readFile()и JSON.parse()это.
Джон Старр Дьюар
1
BufferedReader мог изменить свою подпись. Мне пришлось заменить BufferedReader на BufferedReader, DataReader, где BufferedReader был модулем. См github.com/Gagle/Node-BufferedReader
bnieland
13
Я вижу, что BufferedReader устарел.
Марк Рохкинд,
6

Вы можете использовать поток чтения и конвейер, чтобы читать файл построчно, не считывая весь файл в память за один раз.

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);
});
iamnotsam
источник