Ottieni dati da fs.readFile


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

Registri undefined, perché?


1
fs.readFileSync ha anche funzioni interessanti per leggere un file anche se è nel formato Unicode utf8.
Praneeth,

NB fs.readFile può anche farlo ^ vedi la mia risposta qui sotto
Dominic

Risposte:


348

Per elaborare ciò che ha detto @Raynos, la funzione che hai definito è un callback asincrono. Non viene eseguito immediatamente, ma viene eseguito al termine del caricamento del file. Quando si chiama readFile, il controllo viene restituito immediatamente e viene eseguita la riga di codice successiva. Pertanto, quando si chiama console.log, il callback non è stato ancora richiamato e questo contenuto non è stato ancora impostato. Benvenuti nella programmazione asincrona.

Approcci di esempio

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

O meglio ancora, come mostra l'esempio di Raynos, avvolgi la tua chiamata in una funzione e passa i tuoi callback. (Apparentemente questa è una pratica migliore) Penso che prendere l'abitudine di avvolgere le chiamate asincrone in una funzione che richiede una richiamata ti farà risparmiare un sacco di problemi e codice disordinato.

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

doSomething (function doSomethingAfter(err, result) {
    // process the async result
});

2
La sincronizzazione dell'I / O ha il suo posto: va bene se stai facendo un sistema o uno strumento di piccole dimensioni. Sui sistemi più grandi o le app server è consigliabile evitarlo.
RobW,

28
Non tutto è un web server. E non c'è nulla di orribile nell'usare le versioni di sincronizzazione dei metodi per le chiamate one-shot prima che il server abbia iniziato a ricevere richieste. Chiunque utilizzi Node dovrebbe davvero capire perché prima di usarlo. Sicuramente prima di rant-blog a riguardo.
Erik Reppen,


7
Devi includere 'utf8'dopo il nome file come parametro aggiuntivo, altrimenti restituirà solo un buffer. Vedi: stackoverflow.com/questions/9168737/...
DollarAkshay

252

In realtà esiste una funzione sincrona per questo:

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

asincrono

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

Legge in modo asincrono l'intero contenuto di un file. Esempio:

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

Al callback vengono passati due argomenti (err, data), dove data è il contenuto del file.

Se non viene specificata alcuna codifica, viene restituito il buffer non elaborato.


SINCRONO

fs.readFileSync(filename, [encoding])

Versione sincrona di fs.readFile. Restituisce il contenuto del file denominato nomefile.

Se viene specificata la codifica, questa funzione restituisce una stringa. Altrimenti restituisce un buffer.

var text = fs.readFileSync('test.md','utf8')
console.log (text)

Domanda rapida, a che cosa serve il buffer restituito nella versione sincrona di readFile? Se leggo un file in modo sincrono e non passo alcuna codifica, stampa il buffer, come posso utilizzarlo? Grazie.
codingbbq,

12
Ho avuto esperienza con questo di recente. Diciamo che il nostro buffer è data. if (Buffer.isBuffer( data){ result = data.toString('utf8'); }Ora abbiamo convertito il buffer in testo leggibile. Questo è utile per leggere un file in chiaro o testare il file con tipi di formato. Potrei fare un tentativo / catch per vedere se è un file JSON per esempio; ma solo dopo che il buffer è stato convertito in testo. Guarda qui per maggiori informazioni: nodejs.org/api/buffer.html
Logan

Inoltre, per quanto ne so, i buffer sono flussi di ottetti e sono utili per inviare dati "pezzo per pezzo". Devi aver visto che il buffer è qualcosa di simile AF 42 F1. Molto pratico per la comunicazione client-server-client.
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)
})

6
grazie mille, se avessi 15 voti,
voterei la

Ciao, nella prima riga del tuo codice function readContent(callback), è callbackuna parola riservata? Voglio dire, è questo il modo standard di implementare i callback per le tue funzioni personalizzate? Ho appena iniziato a studiare il nodo.
Amal Antony,

3
Ciao Amal. Callback è semplicemente l'argomento passato alla sua funzione, potrebbe essere evento cqualsiasi nome ti piaccia - non è una parola riservata in Javascript, e presumo che lo stesso si estenda a Node.js.
RealDeal_EE'18

readContent(function (err, content)mi dà un errore di sintassi quando si utilizza la funzione come parametro.
Monsto

66

Utilizzo di Promises con ES7

Uso asincrono con mz / fs

Il mzmodulo fornisce versioni promesse della libreria del nodo principale. Usarli è semplice. Prima installa la libreria ...

npm install mz

Poi...

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

In alternativa puoi scriverli in funzioni asincrone:

async function myReadfile () {
  try {
    const file = await fs.readFile('./Index.html');
  }
  catch (err) { console.error( err ) }
};

6
questo è il futuro e dovrebbe essere molto apprezzato da tutti :) grazie
PirateApp il

2
sembra interessante. Un errore di battitura: 'console.error (catch)' dovrebbe essere 'console.error (err)' presumo).
Philwalk,

2
Se non desideri aggiungere un pacchetto aggiuntivo, prova la soluzione di
@doctorlee di

18
var data = fs.readFileSync('tmp/reltioconfig.json','utf8');

usalo per chiamare un file in modo sincrono, senza codificare il suo output di visualizzazione come buffer.


2
Hai bisogno di una riga vuota prima dei blocchi di codice affinché la bella stampa possa dare il via.
royhowie

informato e il migliore!
Diamante

13

Questa linea funzionerà,

const content = fs.readFileSync('./Index.html', 'utf8');
console.log(content);

1
Sono passati 7 anni :) fs.readFileSyncè il metodo di sincronizzazione, quindi non è necessario await. Attendere è utile con le promesse ( nodejs.org/api/fs.html#fs_fs_promises_api ), quando si desidera scrivere un codice asincrono con una sintassi simile al codice di sincronizzazione.
Karaxuna,

@karaxuna, sì. rimosso. Ho appena incontrato questo caso oggi e ho risolto usando il codice sopra.
Aravin,

1
Questa è la risposta più semplice Se non hai bisogno di asincrono, perché nel mondo dovresti mescolarti con la versione asincrona, con richiamate, asincrono / attendi, ecc.? Questa è la strada da percorrere.
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!");
      });
    });
  }

5
Per favore, non solo inserire il codice nella tua risposta ... spiega perché è diverso e come risolve il problema.
Studocwho,

@doctorlee Questo effettivamente funziona per me, senza alcuna libreria esterna. La spiegazione è necessaria di sicuro.
Ashutosh Chamoli,

7

modo di lettura file di sincronizzazione e asincrono:

//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 Disponibile su read_file .


7

Come detto, fs.readFileè un'azione asincrona. Ciò significa che quando si dice al nodo di leggere un file, è necessario considerare che ci vorrà del tempo e, nel frattempo, il nodo continua a eseguire il codice seguente. Nel tuo caso è:console.log(content); .

È come inviare una parte del codice per un lungo viaggio (come leggere un file di grandi dimensioni).

Dai un'occhiata ai commenti che ho scritto:

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

Ecco perchè content è ancora vuoto quando lo accedi. nodo non ha ancora recuperato il contenuto del file.

Ciò potrebbe essere risolto spostandosi console.log(content)all'interno della funzione di richiamata, subito dopo content = data;. In questo modo vedrai il registro quando il nodo ha finito di leggere il file e dopo contentottiene un valore.


6

Utilizzare la libreria promisify integrata (Nodo 8+) per rendere più eleganti queste vecchie funzioni di callback.

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

Può essere in linea singola const doStuff = async (filePath) => fs.readFileSync(filePath, 'utf8');, non è necessario il wrapping util.promisify.
rab

1
Non usare la versione di sincronizzazione è questo il punto, e dovresti gestire gli errori nel chiamarla
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());
});

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

Questo solo perché il nodo è asincrono e non attenderà la funzione di lettura e non appena il programma si avvia consoliderà il valore come indefinito, il che è vero perché non c'è alcun valore assegnato alla variabile di contenuto. Per gestire possiamo usare promesse, generatori ecc. Possiamo usare le promesse in questo modo.

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.
})

2

Quanto segue è la funzione funzionerebbe per asyncle thencatene di avvolgimento o promessa

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

1

puoi leggere il file di

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

Aggiungendo puoi scrivere su file,

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

e persino incatenarlo insieme

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

1

Per dirla in parole povere, hai a che fare con node.js che è di natura asincrona.

Quando parliamo di asincrono, stiamo parlando di fare o elaborare informazioni o dati mentre trattiamo qualcos'altro. Non è sinonimo di parallelo, si ricorda che.

Il tuo codice:

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

Con l'esempio, fondamentalmente esegue prima la parte console.log, quindi la variabile "contenuto" non è definita.

Se vuoi davvero l'output, fai qualcosa del genere invece:

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

Questo è asincrono. Sarà difficile abituarsi ma, è quello che è. Ancora una volta, questa è una spiegazione approssimativa ma veloce di ciò che è asincrono.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.