Daten aus fs.readFile abrufen

296
var content;
fs.readFile('./Index.html', function read(err, data) {
    if (err) {
        throw err;
    }
    content = data;
});
console.log(content);

Protokolle undefined, warum?

Karaxuna
quelle
1
fs.readFileSync bietet auch coole Funktionen zum Lesen einer Datei, selbst wenn sie im Unicode-Format utf8 vorliegt.
Praneeth
NB fs.readFile kann das auch ^ siehe meine Antwort unten
Dominic

Antworten:

348

Um näher auf das einzugehen, was @Raynos gesagt hat, haben Sie eine asynchrone Rückruffunktion definiert. Es wird nicht sofort ausgeführt, sondern ausgeführt, wenn das Laden der Datei abgeschlossen ist. Wenn Sie readFile aufrufen, wird die Steuerung sofort zurückgegeben und die nächste Codezeile ausgeführt. Wenn Sie also console.log aufrufen, wurde Ihr Rückruf noch nicht aufgerufen, und dieser Inhalt wurde noch nicht festgelegt. Willkommen bei der asynchronen Programmierung.

Beispielansätze

const fs = require('fs');
// First I want to read the file
fs.readFile('./Index.html', function read(err, data) {
    if (err) {
        throw err;
    }
    const content = data;

    // Invoke the next step here however you like
    console.log(content);   // Put all of the code here (not the best solution)
    processFile(content);   // Or put the next step in a function and invoke it
});

function processFile(content) {
    console.log(content);
}

Oder noch besser, wie das Beispiel von Raynos zeigt, wickeln Sie Ihren Anruf in eine Funktion ein und übergeben Sie Ihre eigenen Rückrufe. (Anscheinend ist dies eine bessere Vorgehensweise.) Ich denke, wenn Sie sich angewöhnen, Ihre asynchronen Aufrufe in eine Funktion zu verpacken, die einen Rückruf erfordert, sparen Sie viel Ärger und unordentlichen Code.

function doSomething (callback) {
    // any async callback invokes callback with response
}

doSomething (function doSomethingAfter(err, result) {
    // process the async result
});
Matt Esch
quelle
2
Sync I / O hat seinen Platz - es ist in Ordnung, wenn Sie ein kleines Build-System oder Tool verwenden. Auf größeren Systemen oder Server-Apps empfiehlt es sich, dies zu vermeiden.
RobW
27
Nicht alles ist ein Webserver. Und es ist nichts Schreckliches daran, Synchronversionsversionen von Methoden für One-Shot-Anrufe zu verwenden, bevor der Server Anfragen entgegennimmt. Jeder, der Node verwendet, sollte wirklich verstehen, warum, bevor er es verwendet. Auf jeden Fall vor dem Rant-Bloggen darüber.
Erik Reppen
7
Sie müssen 'utf8'nach dem Dateinamen einen zusätzlichen Parameter einfügen, da sonst nur ein Puffer zurückgegeben wird. Siehe: stackoverflow.com/questions/9168737/…
DollarAkshay
252

Hierfür gibt es tatsächlich eine Synchronfunktion:

http://nodejs.org/api/fs.html#fs_fs_readfilesync_filename_encoding

Asynchron

fs.readFile(filename, [encoding], [callback])

Liest asynchron den gesamten Inhalt einer Datei. Beispiel:

fs.readFile('/etc/passwd', function (err, data) {
  if (err) throw err;
  console.log(data);
});

Dem Rückruf werden zwei Argumente (err, data) übergeben, wobei data der Inhalt der Datei ist.

Wenn keine Codierung angegeben ist, wird der Rohpuffer zurückgegeben.


SYNCHRON

fs.readFileSync(filename, [encoding])

Synchrone Version von fs.readFile. Gibt den Inhalt der Datei mit dem Namen Dateiname zurück.

Wenn die Codierung angegeben ist, gibt diese Funktion eine Zeichenfolge zurück. Andernfalls wird ein Puffer zurückgegeben.

var text = fs.readFileSync('test.md','utf8')
console.log (text)
Logan
quelle
Kurze Frage, wozu dient der Puffer, der in der synchronen Version von readFile zurückgegeben wird? Wenn ich eine Datei synchron lese und keine Codierung übergebe, wird ein Puffer gedruckt. Wie kann ich diesen verwenden? Danke dir.
Codingbbq
12
Ich hatte kürzlich Erfahrung damit. Nehmen wir an, unser Puffer ist data. if (Buffer.isBuffer( data){ result = data.toString('utf8'); }Jetzt haben wir den Puffer in lesbaren Text umgewandelt. Dies ist gut zum Lesen einer Klartextdatei oder zum Testen der Datei anhand von Formattypen. Ich könnte versuchen / fangen, um zu sehen, ob es sich zum Beispiel um eine JSON-Datei handelt. aber erst nachdem der Puffer in Text konvertiert wurde. Weitere Informationen finden Sie hier: nodejs.org/api/buffer.html
Logan
Soweit ich weiß, sind Puffer auch Oktett-Streams und eignen sich gut zum Senden von Daten "Stück für Stück". Sie müssen gesehen haben, dass der Puffer so etwas wie ist AF 42 F1. Sehr praktisch für die Client-Server-Client-Kommunikation.
Logan
113
function readContent(callback) {
    fs.readFile("./Index.html", function (err, content) {
        if (err) return callback(err)
        callback(null, content)
    })
}

readContent(function (err, content) {
    console.log(content)
})
Raynos
quelle
6
Vielen
Hallo, in der ersten Zeile des Codes, function readContent(callback)ist callbackein reserviertes Wort? Ich meine, ist dies die Standardmethode, um Rückrufe für Ihre benutzerdefinierten Funktionen zu implementieren? Ich habe gerade angefangen, Knoten zu lernen.
Amal Antony
3
Hallo Amal. Rückruf ist einfach das Argument, das an seine Funktion übergeben wird, es könnte sein eventoder ein cbeliebiger Name, den Sie mögen - es ist kein reserviertes Wort in Javascript, und ich würde annehmen, dass sich das gleiche auf Node.js erstreckt.
RealDeal_EE'18
readContent(function (err, content)gibt mir einen Syntaxfehler, wenn ich die Funktion als Parameter verwende.
Montag,
66

Versprechen mit ES7 verwenden

Asynchrone Verwendung mit mz / fs

Das mzModul bietet vielversprechende Versionen der Kernknotenbibliothek. Ihre Verwendung ist einfach. Installieren Sie zuerst die Bibliothek ...

npm install mz

Dann...

const fs = require('mz/fs');
fs.readFile('./Index.html').then(contents => console.log(contents))
  .catch(err => console.error(err));

Alternativ können Sie sie in asynchronen Funktionen schreiben:

async function myReadfile () {
  try {
    const file = await fs.readFile('./Index.html');
  }
  catch (err) { console.error( err ) }
};
Evan Carroll
quelle
6
Dies ist die Zukunft und sollte von allen hoch bewertet werden :) Danke
PirateApp
2
sieht interessant aus. Ein Tippfehler: 'console.error (catch)' sollte 'console.error (err)' sein (nehme ich an).
Philwalk
2
Wenn Sie kein zusätzliches Paket hinzufügen möchten, versuchen Sie die folgende Lösung von
@doctorlee
18
var data = fs.readFileSync('tmp/reltioconfig.json','utf8');

Verwenden Sie diese Option, um eine Datei synchron aufzurufen, ohne die angezeigte Ausgabe als Puffer zu codieren.

user2266928
quelle
2
Sie benötigen eine leere Zeile vor den Codeblöcken, damit der hübsche Druck
beginnt
informiert & das Beste!
Diamond
12

Diese Linie wird funktionieren,

const content = fs.readFileSync('./Index.html', 'utf8');
console.log(content);
Aravin
quelle
1
7 Jahre sind vergangen :) fs.readFileSyncist eine Synchronisierungsmethode, daher ist dies nicht erforderlich await. Warten ist nützlich bei Versprechungen ( nodejs.org/api/fs.html#fs_fs_promises_api ), wenn Sie asynchronen Code mit einer Syntax ähnlich dem Synchronisierungscode schreiben möchten.
Karaxuna
@ Karaxuna, ja. entfernt. Ich bin heute gerade auf diesen Fall gestoßen und habe ihn mit dem obigen Code gelöst.
Aravin
1
Dies ist die einfachste Antwort. Wenn Sie kein Async benötigen, warum in aller Welt würden Sie sich überhaupt mit der Async-Version mischen, mit Rückrufen, Async / Warten usw.? Dies ist der richtige Weg.
Master of Ducks
8
const fs = require('fs')
function readDemo1(file1) {
    return new Promise(function (resolve, reject) {
        fs.readFile(file1, 'utf8', function (err, dataDemo1) {
            if (err)
                reject(err);
            else
                resolve(dataDemo1);
        });
    });
}
async function copyFile() {

    try {
        let dataDemo1 = await readDemo1('url')
        dataDemo1 += '\n' +  await readDemo1('url')

        await writeDemo2(dataDemo1)
        console.log(dataDemo1)
    } catch (error) {
        console.error(error);
    }
}
copyFile();

function writeDemo2(dataDemo1) {
    return new Promise(function(resolve, reject) {
      fs.writeFile('text.txt', dataDemo1, 'utf8', function(err) {
        if (err)
          reject(err);
        else
          resolve("Promise Success!");
      });
    });
  }
Doctorlee
quelle
5
Bitte geben Sie nicht einfach Code in Ihre Antwort ein ... erklären Sie, warum es anders ist und wie es das Problem löst.
Studocwho
@doctorlee Das funktioniert bei mir tatsächlich ohne externe Bibliothek. Erklärung ist sicher erforderlich.
Ashutosh Chamoli
7

Lesemethode für synchrone und asynchrone Dateien:

//fs module to read file in sync and async way

var fs = require('fs'),
    filePath = './sample_files/sample_css.css';

// this for async way
/*fs.readFile(filePath, 'utf8', function (err, data) {
    if (err) throw err;
    console.log(data);
});*/

//this is sync way
var css = fs.readFileSync(filePath, 'utf8');
console.log(css);

Node Cheat Verfügbar unter read_file .

Zeeshan Hassan Memon
quelle
7

Wie gesagt, fs.readFileist eine asynchrone Aktion. Wenn Sie den Knoten anweisen, eine Datei zu lesen, müssen Sie berücksichtigen, dass dies einige Zeit dauern wird. In der Zwischenzeit führte der Knoten den folgenden Code weiter aus. In Ihrem Fall ist es:console.log(content); .

Es ist, als würde man einen Teil Ihres Codes für eine lange Reise senden (wie das Lesen einer großen Datei).

Schauen Sie sich die Kommentare an, die ich geschrieben habe:

var content;

// node, go fetch this file. when you come back, please run this "read" callback function
fs.readFile('./Index.html', function read(err, data) {
    if (err) {
        throw err;
    }
    content = data;
});

// in the meantime, please continue and run this console.log
console.log(content);

Deshalb content ist es immer noch leer, wenn Sie es protokollieren. Der Knoten hat den Inhalt der Datei noch nicht abgerufen.

Dies könnte behoben werden, indem Sie console.log(content)direkt danach in die Rückruffunktion wechseln content = data;. Auf diese Weise sehen Sie das Protokoll, wenn der Knoten die Datei gelesen hat und danach contenteinen Wert erhält.

Taituismus
quelle
6

Verwenden Sie die integrierte Promisify-Bibliothek (Knoten 8+), um diese alten Rückruffunktionen eleganter zu gestalten.

const fs = require('fs');
const util = require('util');

const readFile = util.promisify(fs.readFile);

async function doStuff() {
  try {
    const content = await readFile(filePath, 'utf8');
    console.log(content);
  } catch (e) {
    console.error(e);
  }
}
Dominic
quelle
Kann in einer Zeile sein const doStuff = async (filePath) => fs.readFileSync(filePath, 'utf8');, ohne dass util.promisify Wrap erforderlich ist.
Rab
1
Das Nichtverwenden der Synchronisierungsversion ist der Punkt, und Sie sollten Fehler beim Aufrufen behandeln
Dominic
4
var fs = require('fs');
var path = (process.cwd()+"\\text.txt");

fs.readFile(path , function(err,data)
{
    if(err)
        console.log(err)
    else
        console.log(data.toString());
});
Masoud Siahkali
quelle
2
var content;
fs.readFile('./Index.html', function read(err, data) {
    if (err) {
        throw err;
    }
    content = data;
});
console.log(content);

Dies liegt nur daran, dass der Knoten asynchron ist und nicht auf die Lesefunktion wartet. Sobald das Programm gestartet wird, wird der Wert als undefiniert getröstet. Dies ist tatsächlich der Fall, da der Inhaltsvariablen kein Wert zugewiesen ist. Um damit umzugehen, können wir Versprechen, Generatoren usw. verwenden. Wir können Versprechen auf diese Weise verwenden.

new Promise((resolve,reject)=>{
    fs.readFile('./index.html','utf-8',(err, data)=>{
        if (err) {
            reject(err); // in the case of error, control flow goes to the catch block with the error occured.
        }
        else{
            resolve(data);  // in the case of success, control flow goes to the then block with the content of the file.
        }
    });
})
.then((data)=>{
    console.log(data); // use your content of the file here (in this then).    
})
.catch((err)=>{
    throw err; //  handle error here.
})
Nouman Dilshad
quelle
2

Die folgende Funktion würde für asyncWrap- oder Versprechen- thenKetten funktionieren

const readFileAsync =  async (path) => fs.readFileSync(path, 'utf8');
rab
quelle
1

Sie können die Datei von lesen

var readMyFile = function(path, cb) {
      fs.readFile(path, 'utf8', function(err, content) {
        if (err) return cb(err, null);
        cb(null, content);
      });
    };

Hinzufügen Sie können in Datei schreiben,

var createMyFile = (path, data, cb) => {
  fs.writeFile(path, data, function(err) {
    if (err) return console.error(err);
    cb();
  });
};

und sogar verketten

var readFileAndConvertToSentence = function(path, callback) {
  readMyFile(path, function(err, content) {
    if (err) {
      callback(err, null);
    } else {
      var sentence = content.split('\n').join(' ');
      callback(null, sentence);
    }
  });
};
J. Doe
quelle
1

Um es grob auszudrücken, Sie haben es mit node.js zu tun, das asynchroner Natur ist.

Wenn wir über Async sprechen, sprechen wir über das Ausführen oder Verarbeiten von Informationen oder Daten, während wir uns mit etwas anderem befassen. Es ist nicht gleichbedeutend mit parallel, bitte sei daran erinnert.

Dein Code:

var content;
fs.readFile('./Index.html', function read(err, data) {
    if (err) {
        throw err;
    }
    content = data;
});
console.log(content);

Bei Ihrem Beispiel wird zunächst der Teil console.log ausgeführt, sodass die Variable 'content' undefiniert ist.

Wenn Sie die Ausgabe wirklich möchten, gehen Sie stattdessen folgendermaßen vor:

var content;
fs.readFile('./Index.html', function read(err, data) {
    if (err) {
        throw err;
    }
    content = data;
    console.log(content);
});

Dies ist asynchron. Es wird schwer zu gewöhnen sein, aber es ist was es ist. Auch dies ist eine grobe, aber schnelle Erklärung dafür, was Asynchronität ist.

DayIsGreen
quelle