नोड.जेएस: एक सरणी में एक पाठ फ़ाइल पढ़ें। (प्रत्येक पंक्ति सरणी में एक आइटम है।)


164

मैं एक बहुत, बहुत बड़ी फ़ाइल को नोड में एक जावास्क्रिप्ट सरणी में पढ़ना चाहता हूं।

तो, अगर फ़ाइल इस तरह है:

first line
two 
three
...
...

मेरे पास सरणी होगी:

['first line','two','three', ... , ... ] 

फ़ंक्शन इस तरह दिखेगा:

var array = load(filename); 

इसलिए इसे एक स्ट्रिंग के रूप में लोड करने और फिर इसे विभाजित करने का विचार स्वीकार्य नहीं है।


इस प्रश्न को कुछ गंभीर संपादन और सफाई की आवश्यकता है। यह कहता है कि एक टेक्स्ट फ़ाइल को एक सरणी में पढ़ें , लेकिन जब आप सभी उत्तरों और टिप्पणियों को पढ़ते हैं , तो इसका मतलब वास्तव में एक समय में एक पाठ फ़ाइल को एक पंक्ति में पढ़ना है । उस सवाल के लिए @zswang के पास अब तक का सबसे अच्छा जवाब है।
जे एस

हाँ बस उस फ़ाइल को पढ़ें और प्रत्येक पंक्ति को एक सरणी में रखें: stackoverflow.com/a/34033928/1536309
ब्लेयर एंडरसन

जवाबों:


89

यदि आप अंतिम डेटा को एक सरणी में फिट कर सकते हैं तो क्या आप इसे एक स्ट्रिंग में भी फिट नहीं कर पाएंगे और इसे विभाजित कर सकते हैं, जैसा कि सुझाया गया है? किसी भी स्थिति में यदि आप एक बार में फ़ाइल को एक पंक्ति में संसाधित करना चाहते हैं, तो आप इस तरह से कुछ भी आज़मा सकते हैं:

var fs = require('fs');

function readLines(input, func) {
  var remaining = '';

  input.on('data', function(data) {
    remaining += data;
    var index = remaining.indexOf('\n');
    while (index > -1) {
      var line = remaining.substring(0, index);
      remaining = remaining.substring(index + 1);
      func(line);
      index = remaining.indexOf('\n');
    }
  });

  input.on('end', function() {
    if (remaining.length > 0) {
      func(remaining);
    }
  });
}

function func(data) {
  console.log('Line: ' + data);
}

var input = fs.createReadStream('lines.txt');
readLines(input, func);

संपादित करें: ( फोपकिंस द्वारा टिप्पणी के जवाब में ) मुझे लगता है कि (कम से कम नए संस्करणों में) सबस्ट्रिंग डेटा की प्रतिलिपि नहीं बनाता है, लेकिन एक विशेष SlicedString ऑब्जेक्ट बनाता है (v8 स्रोत कोड पर त्वरित नज़र से)। किसी भी मामले में यहाँ एक संशोधन है जो उल्लेख किए गए विकल्प से बचा जाता है ("सभी काम और कोई नाटक जैक को एक सुस्त लड़का बनाता है" के लायक कई मेगाबाइट फ़ाइल पर परीक्षण किया गया है):

function readLines(input, func) {
  var remaining = '';

  input.on('data', function(data) {
    remaining += data;
    var index = remaining.indexOf('\n');
    var last  = 0;
    while (index > -1) {
      var line = remaining.substring(last, index);
      last = index + 1;
      func(line);
      index = remaining.indexOf('\n', last);
    }

    remaining = remaining.substring(last);
  });

  input.on('end', function() {
    if (remaining.length > 0) {
      func(remaining);
    }
  });
}

धन्यवाद। आपके प्रश्न का उत्तर देने के लिए: नहीं, स्ट्रिंग बहुत बड़ी होगी।
चाको

7
मैंने लगभग 2 एमबी या उससे अधिक की फाइलों पर यह कोशिश की थी और यह बहुत धीमी गति से थी, एक स्ट्रिंग के समकालिक रूप से फाइलों में पढ़ने की तुलना में बहुत धीमी। मुझे लगता है कि मुद्दा शेष = शेष है। नोड का "डेटा" आपको एक बार में बहुत कुछ दे सकता है, और हर पंक्ति के लिए वह प्रतिलिपि जल्दी से O (n ^ 2) बन जाती है।
फियोना हॉपकिन्स


444

तुल्यकालिक:

var fs = require('fs');
var array = fs.readFileSync('file.txt').toString().split("\n");
for(i in array) {
    console.log(array[i]);
}

अतुल्यकालिक:

var fs = require('fs');
fs.readFile('file.txt', function(err, data) {
    if(err) throw err;
    var array = data.toString().split("\n");
    for(i in array) {
        console.log(array[i]);
    }
});

11
धन्यवाद। दुर्भाग्य से मुझे अपना प्रश्न संपादित करना पड़ा। मेरा मतलब है कि बड़े पैमाने पर बड़ी फ़ाइल कैसे पढ़ें। एक स्ट्रिंग में यह सब पढ़ना स्वीकार्य नहीं है।
चाको

1
मुझे जिस चीज की जरूरत थी। सरल और त्वरित।
Hcabnettek

16
मुझे ऐसा लगता है कि विंडोज द्वारा बनाई गई एक फ़ाइल पर मुझे ऐसा करना पड़ा, लेकिन मुझे मैक को तोड़ना पड़ा; इतना अधिक मजबूत; _array = string.replace (/ \ r \ n / g, '\ n')। स्प्लिट ('\ n'); दोनों के लिए काम किया
विल हैनकॉक

6
+1 Stackoverflow में कुछ समस्या है। अब, मैं अक्सर बहुत दूर तक स्क्रॉल करने के बाद अत्यधिक वोट किए गए उत्तर पाता हूं। यह भी इसका एक उदाहरण है। इसमें उच्चतम मतदान है लेकिन पृष्ठ के निचले भाग पर स्थित है, बहुत अंतिम। मुझे लगता है कि स्टैकओवरफ़्लो को अपने ऑर्डरिंग एल्गोरिथ्म में सुधार करने की आवश्यकता है।
शास्वत

1
@ शशवत जो व्यक्ति सवाल पूछता है उसे यह तय करना होता है कि सही उत्तर कौन सा है। इस मामले में, उन्हें बड़ी फ़ाइलों के लिए एक स्ट्रीमिंग समाधान की आवश्यकता थी और पूरी फाइल को एक स्ट्रिंग में डालना अस्वीकार्य है। वास्तव में एसओ के साथ कुछ भी गलत नहीं है।
वैध

73

Node.js रीडलाइन मॉड्यूल का उपयोग करना ।

var fs = require('fs');
var readline = require('readline');

var filename = process.argv[2];
readline.createInterface({
    input: fs.createReadStream(filename),
    terminal: false
}).on('line', function(line) {
   console.log('Line: ' + line);
});

1
अफसोस की बात है कि इस समाधान के साथ एक समस्या है : यदि अंतिम \nछोर पर फ़ाइल नहीं है तो आपको अंतिम पंक्ति नहीं मिलती है ! देखें: stackoverflow.com/questions/18450197/…
Yves M.

8
नोड ने उस मुद्दे को \ n stackoverflow.com/a/32599033/3763850
Gemtastic

14

js:

var array = fs.readFileSync('file.txt', 'utf8').split('\n');

ts:

var array = fs.readFileSync('file.txt', 'utf8').toString().split('\n');

1
उपरोक्त को रोकने के लिए TypeError: fs.readFileSync(...).split is not a function, आपको .toString () का उपयोग इस तरह करना चाहिए:var array = fs.readFileSync('file.txt', 'utf8').toString().split('\n');
Qua285

11

रीडलाइन ( प्रलेखन ) का उपयोग करें । यहाँ एक उदाहरण है एक css फ़ाइल पढ़ना, आइकन के लिए पार्स करना और उन्हें लिखना

var results = [];
  var rl = require('readline').createInterface({
    input: require('fs').createReadStream('./assets/stylesheets/_icons.scss')
  });


  // for every new line, if it matches the regex, add it to an array
  // this is ugly regex :)
  rl.on('line', function (line) {
    var re = /\.icon-icon.*:/;
    var match;
    if ((match = re.exec(line)) !== null) {
      results.push(match[0].replace(".",'').replace(":",''));
    }
  });


  // readline emits a close event when the file is read.
  rl.on('close', function(){
    var outputFilename = './icons.json';
    fs.writeFile(outputFilename, JSON.stringify(results, null, 2), function(err) {
        if(err) {
          console.log(err);
        } else {
          console.log("JSON saved to " + outputFilename);
        }
    });
  });


5

बफ़रडियर के साथ , लेकिन फ़ंक्शन अतुल्यकालिक होना चाहिए:

var load = function (file, cb){
    var lines = [];
    new BufferedReader (file, { encoding: "utf8" })
        .on ("error", function (error){
            cb (error, null);
        })
        .on ("line", function (line){
            lines.push (line);
        })
        .on ("end", function (){
            cb (null, lines);
        })
        .read ();
};

load ("file", function (error, lines){
    if (error) return console.log (error);
    console.log (lines);
});

4

मैं सिर्फ @finbarr महान जवाब जोड़ना चाहता हूं, अतुल्यकालिक उदाहरण में थोड़ा ठीक:

अतुल्यकालिक:

var fs = require('fs');
fs.readFile('file.txt', function(err, data) {
    if(err) throw err;
    var array = data.toString().split("\n");
    for(i in array) {
        console.log(array[i]);
    }
    done();
});

@MadPhysicist, किया () है जो async रिलीज करता है। कहते हैं।


3

यह @mtomis द्वारा ऊपर दिए गए उत्तर पर भिन्नता है।

यह लाइनों की एक धारा बनाता है। यह 'डेटा' और 'एंड' ईवेंट का उत्सर्जन करता है, जिससे आप स्ट्रीम के अंत को संभाल सकते हैं।

var events = require('events');

var LineStream = function (input) {
    var remaining = '';

    input.on('data', function (data) {
        remaining += data;
        var index = remaining.indexOf('\n');
        var last = 0;
        while (index > -1) {
            var line = remaining.substring(last, index);
            last = index + 1;
            this.emit('data', line);
            index = remaining.indexOf('\n', last);
        }
        remaining = remaining.substring(last);
    }.bind(this));

    input.on('end', function() {
        if (remaining.length > 0) {
            this.emit('data', remaining);
        }
        this.emit('end');
    }.bind(this));
}

LineStream.prototype = new events.EventEmitter;

इसे एक आवरण के रूप में उपयोग करें:

var lineInput = new LineStream(input);

lineInput.on('data', function (line) {
    // handle line
});

lineInput.on('end', function() {
    // wrap it up
});

1
आप घटनाओं के बीच साझा की घटनाओं के साथ समाप्त होगा। var EventEmitter = require('events').EventEmitter; var util = require('util'); function GoodEmitter() { EventEmitter.call(this); } util.inherits(GoodEmitter, EventEmitter);
CTAPbIu_MABP

आप किस उदाहरण के बारे में बात कर रहे हैं?
25

1
var li1 = new LineStream(input1), li2 = new LineStream(input2);तब गिनने की कोशिश करें कि हर एक के लिए कितनी बार 'अंत' निकाल दिया जाता है
CTAPbIu_MABP

इसे आजमाया। प्रत्येक उदाहरण के लिए एक बार 'अंत' निकाल दिया गया था। var fs = require('fs'); var input1 = fs.createReadStream('text.txt'); var ls1 = new LineStream(input1); ls1.on('data', function (line) { console.log('1:line=' + line); }); ls1.on('end', function (line) { console.log('1:fin'); }); var input2 = fs.createReadStream('text.txt'); var ls2 = new LineStream(input2); ls2.on('data', function (line) { console.log('2:line=' + line); }); ls2.on('end', function (line) { console.log('2:fin'); }); आउटपुट: पाठ फ़ाइल में प्रत्येक पंक्ति को प्रत्येक उदाहरण के लिए एक बार निकाल दिया गया था। तो 'अंत' था।
इंरी

2

मुझे वही समस्या थी, और मैंने इसे मॉड्यूल लाइन-बाय-लाइन के साथ हल किया है

https://www.npmjs.com/package/line-by-line

कम से कम मेरे लिए समकालिक और अतुल्यकालिक मोड में एक आकर्षण की तरह काम करता है।

इसके अलावा, समाप्ति के साथ समस्याएँ समाप्त नहीं होने वाली \ n विकल्प के साथ हल की जा सकती हैं:

{ encoding: 'utf8', skipEmptyLines: false }

लाइनों का समकालिक प्रसंस्करण:

var LineByLineReader = require('line-by-line'),
    lr = new LineByLineReader('big_file.txt');

lr.on('error', function (err) {
    // 'err' contains error object
});

lr.on('line', function (line) {
    // 'line' contains the current line without the trailing newline character.
});

lr.on('end', function () {
    // All lines are read, file is closed now.
}); 

2

Node.js v8 का उपयोग करना या बाद में एक नई सुविधा है जो सामान्य फ़ंक्शन को एक async फ़ंक्शन में परिवर्तित करती है।

util.promisify

यह एक कमाल की विशेषता है। यहाँ एक सरणी में txt फ़ाइल से 10000 नंबरों को पार्स करने का उदाहरण है, संख्याओं पर मर्ज के प्रकार का उपयोग करके उलटा गिनती करना।

// read from txt file
const util = require('util');
const fs = require('fs')
fs.readFileAsync = util.promisify(fs.readFile);
let result = []

const parseTxt = async (csvFile) => {
  let fields, obj
  const data = await fs.readFileAsync(csvFile)
  const str = data.toString()
  const lines = str.split('\r\n')
  // const lines = str
  console.log("lines", lines)
  // console.log("str", str)

  lines.map(line => {
    if(!line) {return null}
    result.push(Number(line))
  })
  console.log("result",result)
  return result
}
parseTxt('./count-inversion.txt').then(() => {
  console.log(mergeSort({arr: result, count: 0}))
})

1

सरणी में एक बड़ी फ़ाइल पढ़ने के लिए आप लाइन से लाइन पढ़ सकते हैं या चंक द्वारा चंक कर सकते हैं।

लाइन बाय लाइन यहाँ मेरे जवाब का संदर्भ लें

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

var lines = [];

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

chunk by chunk इस लेख का संदर्भ लें

var offset = 0;
var chunkSize = 2048;
var chunkBuffer = new Buffer(chunkSize);
var fp = fs.openSync('filepath', 'r');
var bytesRead = 0;
while(bytesRead = fs.readSync(fp, chunkBuffer, 0, chunkSize, offset)) {
    offset += bytesRead;
    var str = chunkBuffer.slice(0, bytesRead).toString();
    var arr = str.split('\n');

    if(bytesRead = chunkSize) {
        // the last item of the arr may be not a full line, leave it to the next chunk
        offset -= arr.pop().length;
    }
    lines.push(arr);
}
console.log(lines);
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.