Node.js kullanarak bir metin dosyası mı okuyorsunuz?


124

Terminalde bir metin dosyası geçirmem ve ardından içindeki verileri okumam gerekiyor, bunu nasıl yapabilirim?

node server.js file.txt

Terminalden yolu nasıl geçebilirim, diğer tarafta bunu nasıl okuyabilirim?


Kendinizi komut satırına daha fazla seçenek eklerken bulursanız, Optimist'i kullanabilirsiniz .
Jess

stackoverflow.com/questions/6156501/… bir metin dosyasını okumanın başka bir yolunu gösteriyor
Marc Durdin

Yanıtlar:


172

process.argvDosya adını almak için komut satırı bağımsız değişkenlerine erişmek için diziyi ve dosyayı okumak için Dosya Sistemi modülünü (fs) kullanmak isteyeceksiniz . Örneğin:

// 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)
});

Bunu sizin için biraz parçalamak için process.argvgenellikle iki uzunluğa sahip olacaksınız, sıfırıncı öğe "düğüm" yorumlayıcısı ve ilki düğümün o anda çalıştırdığı komut dosyası, bundan sonraki öğeler komut satırından geçirildi. Argv'den bir dosya adı aldığınızda, dosyayı okumak ve içeriğiyle istediğinizi yapmak için dosya sistemi işlevlerini kullanabilirsiniz. Örnek kullanım şöyle görünecektir:

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

[Düzenle] @wtfcoder'ın da belirttiği gibi, " fs.readFile()" yöntemini kullanmak en iyi fikir olmayabilir, çünkü dosyayı geri çağırma işlevine vermeden önce dosyanın tüm içeriğini arabelleğe alacaktır. Bu arabelleğe alma, potansiyel olarak çok fazla bellek kullanabilir, ancak daha da önemlisi, node.js'nin temel özelliklerinden biri olan eşzamansız, olaylı G / Ç'den yararlanmaz.

Büyük bir dosyayı (veya herhangi bir dosyayı, gerçekten) işlemenin "düğüm" yolu fs.read(), işletim sisteminden elde edilebilen her bir parçayı kullanmak ve işlemek olacaktır . Ancak, dosyayı bu şekilde okumak, dosyayı kendi (muhtemelen) kademeli olarak ayrıştırmanızı / işlemenizi gerektirir ve bir miktar arabelleğe alma kaçınılmaz olabilir.


Harika, çok teşekkürler, çok yardımcı. Bu verileri satırlara nasıl bölebilirim?
fantezi

10
@fancy: try var lines = data.split(/\r?\n/);, ardından "satırlar" dizisi her satıra sahip olacaktır.
maerics

1
Metin dosyası büyükse bu iyi bir fikir değildir, çünkü hepsi belleğe okunacaktır, 1000 mb'lik bir CSV dosyasını fs.createFilestream'e baktığınızda işliyorsanız, veri parçacıkları gibi satır bölmeye dikkat etmeniz gerekecektir. (çoğu durumda) hat sınırlarına düşmeyecek (bazı insanlar zaten çözümler buldu - google)
Mâtt Frëëman

1
@wtfcoder: evet, çok iyi bir nokta. Niyetim sadece komut satırında adı verilen bir dosyayı okumanın basit durumunu göstermekti; bu sorunun kapsamı dışında kalan pek çok incelik (özellikle performans) var.
maerics

Eşzamanlı bir akış kullanarak çok büyük bir dosyayı ayrıştırmak için benzer bir soruya bir çözüm gönderdim. bkz: stackoverflow.com/questions/16010915/…
Gerard

35

Düğümlü fs kullanın.

var fs = require('fs');

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

Bunun eşzamanlı versiyon olduğunu unutmayın .
Rich Werden

@RichWerden Bu bağlamda "eşzamanlı" derken neyi kastediyorsunuz?
Json

1
Düğümde, bir şey "eşzamanlı" olduğunda, sistemin başka bir şey yapmasını durdurur / engeller. Diyelim ki bir düğüm web sunucunuz var - yukarıdakiler olurken başka istekler gelirse, sunucu dosyayı okumakla meşgul olduğu için yanıt vermez / yanıt veremez.
Rich Werden

27

IMHO'dan fs.readFile()kaçınılmalıdır çünkü TÜM dosyayı belleğe yükler ve tüm dosya okunana kadar geri aramayı çağırmaz.

Bir metin dosyasını okumanın en kolay yolu, onu satır satır okumaktır. BufferedReader tavsiye ederim :

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 veya json dosyaları gibi karmaşık veri yapıları için bir ayrıştırıcı kullanmanız gerekir (dahili olarak tamponlu bir okuyucu da kullanmalıdır).


7
Bu tekniği gösterdiğin için teşekkürler. Bunun en iyi yol olabileceği konusunda haklısınız, ancak bu soru bağlamında biraz kafa karıştırıcı olduğunu düşündüm, ki bence bu iddiasız bir kullanım durumu soruyor. Yukarıda belirtildiği gibi, bir komut satırı aracına iletilen sadece küçük bir dosyaysa, fs.readFile()veya kullanmamak için bir neden yoktur fs.readFileSync(). Dikkat çekici bir beklemeye neden olması için çok büyük bir dosya olmalı. Package.json gibi bir JSON yapılandırma dosyası, 1 kb altında olması muhtemeldir yüzden sadece can fs.readFile()ve JSON.parse()onu.
John Starr Dewar

1
BufferedReader imzasını değiştirmiş olabilir. BufferedReader'ı BufferedReader, DataReader ile değiştirmek zorunda kaldım, burada BufferedReader modüldü. Bkz. Github.com/Gagle/Node-BufferedReader
bnieland

13
BufferedReader'ın artık kullanımdan kaldırıldığını görüyorum.
Marc Rochkind

6

Tüm dosyayı bir kez belleğe okumadan dosyayı satır satır okumak için okuma akışını ve yöneltmeyi kullanabilirsiniz.

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

Sonunda çalışmaya başladığım eksiksiz bir örnek gönderiyorum. Burada rooms/rooms.txtbir komut dosyasından bir dosya okuyorumrooms/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);
});
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.