Читати текстовий файл за допомогою Node.js?


124

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

node server.js file.txt

Як мені пройти шлях від терміналу, як прочитати це з іншого боку?


Якщо ви знайдете в командному рядку додаткові параметри, ви можете скористатися оптимістом .
Джесс

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!

[Редагувати] Як згадує @wtfcoder, використання " fs.readFile()" методу може бути не найкращою ідеєю, оскільки воно буде буферувати весь вміст файлу, перш ніж передати його функції зворотного виклику. Ця буферизація може потенційно використовувати багато пам'яті, але, що ще важливіше, вона не використовує одну з основних особливостей node.js - асинхронний, парний введення / виведення.

Способом "вузла" для обробки великого файлу (або будь-якого файлу, справді) було б використання fs.read()та обробка кожного доступного фрагмента, як це доступно в операційній системі. Однак читання файлу як такого вимагає зробити власний (можливо) поступовий аналіз / обробку файлу та деяку кількість буферизації може бути неминучим.


Дивовижне, спасибі велике, дуже корисне. Як я можу розділити ці дані за рядком?
фантазія

10
@fancy: спробуйте var lines = data.split(/\r?\n/);, тоді масив "рядки" матиме кожен рядок.
maerics

1
Це не гарна ідея, якщо текстовий файл є великим, оскільки він буде прочитаний у пам'яті, якщо ви обробляєте, скажімо, файл CSV 1000mb дивимось на fs.createFilestream, вам потрібно буде подбати про розбиття рядків, хоча як фрагменти даних звичайно (в більшості випадків) падіння на межі лінії (деякі люди вже придумали рішення - google)
Mâtt Frëëman

1
@wtfcoder: так, дуже хороший момент. Моя мета полягала лише в тому, щоб продемонструвати простий випадок читання файлу, названого в командному рядку; очевидно, є багато тонкощів (особливо ефективності), які виходять за рамки цього питання.
maerics

Я розмістив рішення аналогічного питання для розбору дуже великого файлу, використовуючи синхронний потік. дивіться: stackoverflow.com/questions/16010915/…
Джерард

35

Призначте fs з вузлом.

var fs = require('fs');

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

Зауважте, що це синхронна версія.
Річ Верден

@RichWerden, що ви розумієте під "синхронним" у цьому контексті?
Json

1
У «Вузлі», коли щось є «синхронним», воно зупиняє / блокує систему робити щось інше. Скажімо, у вас є веб-сервер вузла - якщо будь-які інші запити надходять, поки відбувається вищезазначене, сервер не зможе / не зможе відповісти, оскільки він зайнятий читанням файлу.
Річ Верден

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

Ви можете використовувати 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);
});
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.