नोड में फ़ाइल कैसे संलग्न करें?


505

मैं एक लॉग फ़ाइल के लिए एक स्ट्रिंग संलग्न करने की कोशिश कर रहा हूँ । हालाँकि राइटफाइल स्ट्रिंग लिखने से पहले हर बार सामग्री मिटा देगा।

fs.writeFile('log.txt', 'Hello Node', function (err) {
  if (err) throw err;
  console.log('It\'s saved!');
}); // => message.txt erased, contains only 'Hello Node'

किसी भी विचार कैसे यह आसान तरीका है?

जवाबों:


798

कभी-कभी एपेंड के लिए, आप उपयोग कर सकते हैं appendFile, जो हर बार कॉल किए जाने पर एक नई फ़ाइल हैंडल बनाता है:

अतुल्य रूप से :

const fs = require('fs');

fs.appendFile('message.txt', 'data to append', function (err) {
  if (err) throw err;
  console.log('Saved!');
});

समान रूप से :

const fs = require('fs');

fs.appendFileSync('message.txt', 'data to append');

लेकिन अगर आप एक ही फाइल को बार-बार जोड़ते हैं, तो फाइल हैंडल को फिर से उपयोग करना बेहतर है ।


6
चूँकि Node v0.8.0
denysonique

59
क्या किसी को पता है कि अगर fs.appendFile फ़ाइल के लिंक को खुला रखता है तो एपेंड तेजी से होते हैं? (प्रत्येक लेखन को खोलने / बंद करने के बजाय) नोडज ..org
api

7
मामले में यह आसान है: ध्यान दें कि यह async है। इसके परिणामस्वरूप अजीब समय और अन्य चीजें हो सकती हैं। Ex: यदि आपके पास process.exit()बस है fs.appendFile, तो आउटपुट भेजे जाने से पहले आप बाहर निकल सकते हैं। (प्रयोग returnठीक है।)
साइलेंटसेलेल

6
इससे भी बदतर स्थिति है, आप, तुल्यकालिक संस्करण का उपयोग कर सकते हैं appendFileSyncnodejs.org/api/… लेकिन आप नोड के महान लाभों में से एक को खो सकते हैं, जो कि async ऑपरेशंस है। सुनिश्चित करें कि आप त्रुटियां पकड़ते हैं। शायद कुछ OSes पर, आप उसी समय फ़ाइल हैंडल का अनुरोध करने से वंचित हो सकते हैं। उस पर यकीन नहीं है।
साइलेंसेट

5
@chrisdew अपडेट के लिए धन्यवाद .. लेकिन ... अगर हम यहां स्वीकृत उत्तर का उपयोग नहीं कर रहे हैं, तो हम क्या करने वाले हैं? आपने इस डिलेमा को कैसे हल किया?
zipzit

214

जब आप किसी लॉग फ़ाइल में लिखना चाहते हैं, अर्थात फ़ाइल के अंत में डेटा जोड़ना, कभी उपयोग करें appendFileappendFileआपके द्वारा जोड़े गए डेटा के प्रत्येक टुकड़े के लिए एक फ़ाइल हैंडल खोलता है, थोड़ी देर के बाद आपको एक सुंदर EMFILEत्रुटि मिलती है ।

मैं जोड़ सकता हूं कि appendFileए की तुलना में उपयोग करना आसान नहीं है WriteStream

उदाहरण के साथ appendFile:

console.log(new Date().toISOString());
[...Array(10000)].forEach( function (item,index) {
    fs.appendFile("append.txt", index+ "\n", function (err) {
        if (err) console.log(err);
    });
});
console.log(new Date().toISOString());

मेरे कंप्यूटर पर 8000 तक, आप डेटा को फ़ाइल में जोड़ सकते हैं, फिर आप इसे प्राप्त करेंगे:

{ Error: EMFILE: too many open files, open 'C:\mypath\append.txt'
    at Error (native)
  errno: -4066,
  code: 'EMFILE',
  syscall: 'open',
  path: 'C:\\mypath\\append.txt' }

इसके अलावा, appendFile यह सक्षम होने पर लिखेंगे, इसलिए आपके लॉग टाइमस्टैम्प द्वारा नहीं लिखे जाएंगे। आप उदाहरण के साथ परीक्षण कर सकते हैं, 100000 के स्थान पर 1000 सेट कर सकते हैं, ऑर्डर यादृच्छिक होगा, फ़ाइल तक पहुंच पर निर्भर करता है।

यदि आप किसी फ़ाइल में संलग्न करना चाहते हैं, तो आपको इस तरह एक लिखने योग्य स्ट्रीम का उपयोग करना होगा :

var stream = fs.createWriteStream("append.txt", {flags:'a'});
console.log(new Date().toISOString());
[...Array(10000)].forEach( function (item,index) {
    stream.write(index + "\n");
});
console.log(new Date().toISOString());
stream.end();

आप जब चाहें इसे समाप्त कर दें। आपको उपयोग करने की भी आवश्यकता नहीं है stream.end(), डिफ़ॉल्ट विकल्प है AutoClose:true, इसलिए जब आपकी प्रक्रिया समाप्त हो जाएगी, तो आपकी फ़ाइल समाप्त हो जाएगी और आप बहुत सारी फाइलें खोलने से बचेंगे।


2
इस पर हाजिर है।
पोग्रिंडिस

3
महान उत्तर के लिए धन्यवाद, लेकिन मेरा संदेह यह है कि जावास्क्रिप्ट की अतुल्यकालिक प्रकृति के कारण, यह stream.end()पहले निष्पादित करेगा stream.write(), इसलिए हमें उपयोग नहीं करना चाहिए stream.end(), जैसा कि आपने उल्लेख किया है कि AutoClose:Trueयह एक डिफ़ॉल्ट विकल्प है फिर एक पंक्ति लिखने से परेशान क्यों नहीं है उपयोग।
आशीष कुमार

13
due to asynchronous nature of Javascript... क्या? Array.forEach एक तुल्यकालिक ऑपरेशन है। जेएस तुल्यकालिक है। यह सिर्फ एसिंक्रोनस संचालन को प्रबंधित करने के कुछ तरीके प्रदान करने के लिए होता है, जैसे कि वादे और async / प्रतीक्षा।
Sharcoux

1
मैं fs.appendFileबहुत सी खुली फाइलों में परिणाम का अनुमान लगाऊंगा क्योंकि आप इसे एसिंक्रोनस तरीके से निष्पादित करते हैं (आप बस अतुल्यकालिक रूप से 10000 फ़ाइल हैंडल बना रहे हैं), मेरा मानना ​​है appendFileSyncकि समान समस्या नहीं होगी, fs.appendFileउचित अंतराल के साथ भी नहीं (1s संभवतः पर्याप्त से अधिक है) या कतारबद्ध करना।
सेब सेब

1
@RedwolfPrograms व्यस्त सर्वर लॉग के लिए, शायद सच है। निष्पादन लॉग के लिए एक बार, शायद नहीं। वैसे भी, मैं सिर्फ यह बताता हूं कि इस उत्तर में बिंदु (कम से कम कारण) सही नहीं है।
सेब सेब

122

CreateWriteStream का उपयोग करने वाला आपका कोड हर लिखने के लिए एक फाइल डिस्क्रिप्टर बनाता है। log.end बेहतर है क्योंकि यह लिखने के तुरंत बाद नोड को बंद करने के लिए कहता है।

var fs = require('fs');
var logStream = fs.createWriteStream('log.txt', {flags: 'a'});
// use {flags: 'a'} to append and {flags: 'w'} to erase and write a new file
logStream.write('Initial line...');
logStream.end('this is the end line');

6
पहली पंक्ति लापता! होना चाहिए 'var fs = आवश्यकता (' fs ');)
स्टॉर्मबाइट्स

5
या शायद और भी बेहतर var fs = require('graceful-fs'), जिसने कुछ ज्ञात समस्याओं को दूर किया है। अधिक जानकारी के लिए डॉक्स देखें ।
मार्को बोनासी

3
प्रारंभिक और अंतिम पंक्ति दोनों एक ही लाइन पर हैं :-p
binki

5
कृपया ध्यान दें : यदि आप उपयोग कर रहे हैं fs.createWriteStream, तो उपयोग करें flags। यदि आप उपयोग कर रहे हैं fs.writeFileतो यह है flag। कृपया अधिक जानकारी के लिए नोड जेएस डॉक्स - फाइल सिस्टम देखें।
अनिश नायर

2
सावधान रहे! पैरामीटर "झंडे" नहीं है, लेकिन "झंडा" (एकवचन): नोडज.ओआरपी
बेनी

25

इसके अलावा appendFile, आप writeFileमौजूदा फ़ाइल में डेटा संलग्न करने के लिए एक ध्वज भी पास कर सकते हैं ।

fs.writeFile('log.txt', 'Hello Node',  {'flag':'a'},  function(err) {
    if (err) {
        return console.error(err);
    }
});

ध्वज 'ए' पास करके, डेटा फ़ाइल के अंत में संलग्न किया जाएगा।


3
कृपया ध्यान दें : यदि आप उपयोग कर रहे हैं fs.createWriteStream, तो उपयोग करें flags। यदि आप उपयोग कर रहे हैं fs.writeFileतो यह है flag। कृपया अधिक जानकारी के लिए नोड जेएस डॉक्स - फाइल सिस्टम देखें।
अनीश नायर

19

आपको इसे खोलने की आवश्यकता है, फिर इसे लिखें।

var fs = require('fs'), str = 'string to append to file';
fs.open('filepath', 'a', 666, function( e, id ) {
  fs.write( id, 'string to append to file', null, 'utf8', function(){
    fs.close(id, function(){
      console.log('file closed');
    });
  });
});

यहां कुछ लिंक दिए गए हैं जो मापदंडों को समझाने में मदद करेंगे

ओपन
राइट
पास


EDIT : यह उत्तर अब मान्य नहीं है, अप्लाई करने के लिए नई fs.appendFile विधि देखें।


1
सुपरकोबरा की तरह देखें लॉग फ़ाइल में लगातार लॉग लिखते हैं, इस मामले में fs.write का उपयोग अनुशंसित नहीं है, इसके बजाय fs.createWriteStream का उपयोग करें। पढ़िए njjs.org/docs/v0.4.8/api/all.html#fs.write
नाराज कीवी

10
उत्तर अब नोड्ज v0.4.10 के रूप में सटीक नहीं है।
रुबेन तन

यह 666 की बजाय '0666' होना चाहिए।
झुआंग

13

Node.js 0.8 में है fs.appendFile:

fs.appendFile('message.txt', 'data to append', (err) => {
  if (err) throw err;
  console.log('The "data to append" was appended to file!');
});

प्रलेखन


3
fd = fs.openSync(path.join(process.cwd(), 'log.txt'), 'a')
fs.writeSync(fd, 'contents to append')
fs.closeSync(fd)

5
कुछ भी सिंक () लगभग हमेशा एक बुरा विचार है जब तक कि आप 100% सुनिश्चित नहीं हो जाते कि आपने इसे पूरी तरह से कर लिया है। फिर भी, आप शायद गलत कर रहे हैं।
ज़ेन का दावा

4
इसका मतलब यह नहीं है कि यह गलत है। यह सिर्फ सिंक्रोनाइज़ करता है। Node.js के लिए सर्वोत्तम अभ्यास नहीं हो सकता है, लेकिन यह समर्थित है।
लुइस आर।

2
मैं वाक्यांश के बोलचाल के इंटरनेट-मेमे अर्थ में "उर डिन इट गलत" का उपयोग कर रहा था। जाहिर है यह समर्थित है = पी
ज़ेन क्लेस

7
Async पर सहमत हैं, लेकिन कभी-कभी यदि आप सिर्फ एक इंटरैक्टिव स्क्रिप्ट लिख रहे हैं, तो सिंक ठीक है।
ब्रायनमैक

7
यदि आप सिंगल यूजर कमांड लाइन ऐप (उदाहरण के लिए कुछ सामान करने के लिए स्क्रिप्ट) कर रहे हैं तो सिंक्रोनस लिखना बिल्कुल ठीक है। इस तरह यह सामान करने के लिए तेज़ है। यदि इस प्रयोजन के लिए नहीं है तो नोड में सिंक विधि क्यों होगी?
Jan atwięcki

3

यदि आप फ़ाइल में लाइन द्वारा लॉग लाइन लिखने का एक आसान और तनाव-मुक्त तरीका चाहते हैं, तो मैं सलाह देता हूं fs-extra की :

const os = require('os');
const fs = require('fs-extra');

const file = 'logfile.txt';
const options = {flag: 'a'};

async function writeToFile(text) {
  await fs.outputFile(file, `${text}${os.EOL}`, options);
}

writeToFile('First line');
writeToFile('Second line');
writeToFile('Third line');
writeToFile('Fourth line');
writeToFile('Fifth line');

नोड v8.9.4 के साथ परीक्षण किया गया।


2

मेरा दृष्टिकोण बल्कि विशेष है। मैं मूल रूप से WriteStreamसमाधान का उपयोग करता हूं, लेकिन वास्तव में उपयोग करके fd को 'बंद' किए बिना stream.end()। इसके बजाय मैं cork/ का उपयोग करता हूं uncork। इसे कम रैम उपयोग (यदि यह किसी के लिए भी मायने रखता है) का लाभ मिला और मुझे विश्वास है कि यह लॉगिंग / रिकॉर्डिंग (मेरा मूल उपयोग मामला) के लिए उपयोग करना अधिक सुरक्षित है।

निम्नलिखित एक बहुत सरल उदाहरण है। ध्यान दें, मैंने सिर्फ forशोकेस के लिए एक छद्म पाश जोड़ा - उत्पादन कोड में मैं वेबसैट संदेशों का इंतजार कर रहा हूं।

var stream = fs.createWriteStream("log.txt", {flags:'a'});
for(true) {
  stream.cork();
  stream.write("some content to log");
  process.nextTick(() => stream.uncork());
}

uncork अगले टिक में फ़ाइल में डेटा फ्लश करेगा।

मेरे परिदृश्य में विभिन्न आकारों में प्रति सेकंड 200 लिखने तक की चोटियाँ हैं। हालांकि रात के समय में प्रति मिनट केवल एक मुट्ठी लिखने की जरूरत होती है। चरम समय के दौरान भी कोड सुपर विश्वसनीय काम कर रहा है।


1

मैं यह सुझाव केवल इसलिए देता हूं क्योंकि खुले झंडे पर नियंत्रण कभी-कभी उपयोगी होता है, उदाहरण के लिए, आप इसे पहले एक मौजूदा फ़ाइल को अलग करना चाहते हैं और फिर इसे लिखने की एक श्रृंखला को जोड़ सकते हैं - जिस स्थिति में फ़ाइल खोलते समय 'w' ध्वज का उपयोग करें और इसे तब तक बंद न करें जब तक कि सभी लिख न जाएं। बेशक परिशिष्ट हो सकता है कि आप क्या कर रहे हैं :-)

  fs.open('log.txt', 'a', function(err, log) {
    if (err) throw err;
    fs.writeFile(log, 'Hello Node', function (err) {
      if (err) throw err;
      fs.close(log, function(err) {
        if (err) throw err;
        console.log('It\'s saved!');
      });
    });
  });


1

का उपयोग करना fs.appendFileया fsPromises.appendFileजब आप एक फ़ाइल के लिए कुछ संलग्न करने के लिए की जरूरत है सबसे तेज और सबसे मजबूत विकल्प हैं।

सुझाए गए कुछ उत्तरों के विपरीत, यदि फ़ाइल पथ appendFileफ़ंक्शन को आपूर्ति की जाती है , तो यह वास्तव में अपने आप बंद हो जाता है । केवल जब आप किसी फ़ाइलहैंडल में पास होते हैं, जो आपको किसी चीज़ से मिलता हैfs.open() आपको इसे बंद करने का ध्यान रखना होता है।

मैंने इसे एक फाइल में 50,000 से अधिक लाइनों के साथ आज़माया।

उदाहरण :

(async () => {
  // using appendFile.
  const fsp = require('fs').promises;
  await fsp.appendFile(
    '/path/to/file', '\r\nHello world.'
  );

  // using apickfs; handles error and edge cases better.
  const apickFileStorage = require('apickfs');
  await apickFileStorage.writeLines(
    '/path/to/directory/', 'filename', 'Hello world.'
  );
})();

यहाँ छवि विवरण दर्ज करें

Ref: https://github.com/nodejs/node/issues/7560
उदाहरण निष्पादन: https://github.com/apickjs/apickFS/blob/master/writeLines.js


0

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

var fs = require('fs');

function ReadAppend(file, appendFile){
  fs.readFile(appendFile, function (err, data) {
    if (err) throw err;
    console.log('File was read');

    fs.appendFile(file, data, function (err) {
      if (err) throw err;
      console.log('The "data to append" was appended to file!');

    });
  });
}
// edit this with your file names
file = 'name_of_main_file.csv';
appendFile = 'name_of_second_file_to_combine.csv';
ReadAppend(file, appendFile);

0

ऐसा करने का एक आसान तरीका है

const fs = require('fs');
fs.appendFileSync('file.txt', 'message to append into file');

क्या आसान है? क्या आपने शीर्ष उत्तर की जांच की है, जो बिल्कुल समान appendFileSyncसमाधान देता है ?
डेन डस्केलस्क्यू

0
const inovioLogger = (logger = "") => {
    const log_file = fs.createWriteStream(__dirname + `/../../inoviopay-${new Date().toISOString().slice(0, 10)}.log`, { flags: 'a' });
    const log_stdout = process.stdout;
    log_file.write(logger + '\n');
}

0

डेन्सोनिक्स के जवाब के अलावा , कभी-कभी अतुल्यकालिक प्रकार के appendFileऔर NodeJS में अन्य एसिंक्स विधियों का उपयोग किया जाता है, जहां कॉलबैक पास होने के बजाय रिटर्न का वादा किया जाता है। यह करने के लिए आपको promisifyHOF के साथ फ़ंक्शन को लपेटने या वादों के नामस्थान से async फ़ंक्शंस आयात करने की आवश्यकता है:

const { appendFile } = require('fs').promises;

await appendFile('path/to/file/to/append', dataToAppend, optionalOptions);

मुझे उम्मीद है कि यह मदद करेगा 😉

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.