Obtenir des données de fs.readFile


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

Journaux undefined, pourquoi?


1
fs.readFileSync a également des fonctionnalités intéressantes pour lire un fichier même s'il est au format unicode utf8.
Praneeth

NB fs.readFile peut également le faire ^ voir ma réponse ci
Dominic

Réponses:


348

Pour développer ce que @Raynos a dit, la fonction que vous avez définie est un rappel asynchrone. Il ne s'exécute pas immédiatement, il s'exécute plutôt lorsque le chargement du fichier est terminé. Lorsque vous appelez readFile, le contrôle est renvoyé immédiatement et la ligne de code suivante est exécutée. Ainsi, lorsque vous appelez console.log, votre rappel n'a pas encore été appelé et ce contenu n'a pas encore été défini. Bienvenue dans la programmation asynchrone.

Exemples d'approches

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

Ou mieux encore, comme le montre l'exemple de Raynos, encapsulez votre appel dans une fonction et passez vos propres rappels. (Apparemment, c'est une meilleure pratique) Je pense que prendre l'habitude d'encapsuler vos appels asynchrones dans une fonction qui prend un rappel vous évitera beaucoup de problèmes et de code désordonné.

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

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

2
Les E / S de synchronisation ont leur place - c'est bien si vous faites un petit système ou outil de construction. Sur les grands systèmes ou les applications serveur, la meilleure pratique consiste à l'éviter.
RobW

28
Tout n'est pas un serveur Web. Et il n'y a rien d'horrible à propos de l'utilisation horrible des versions de synchronisation des méthodes pour les appels uniques avant que le serveur ne commence à prendre les demandes. Quiconque utilise Node devrait vraiment comprendre pourquoi avant de l'utiliser. Certainement avant de bloguer à ce sujet.
Erik Reppen


7
Vous devez inclure 'utf8'après le nom de fichier comme paramètre supplémentaire, sinon il renverra simplement un tampon. Voir: stackoverflow.com/questions/9168737/…
DollarAkshay

252

Il existe en fait une fonction synchrone pour cela:

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

Asynchrone

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

Lit de manière asynchrone l'intégralité du contenu d'un fichier. Exemple:

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

Le rappel est passé deux arguments (err, data), où data est le contenu du fichier.

Si aucun codage n'est spécifié, le tampon brut est renvoyé.


SYNCHRONE

fs.readFileSync(filename, [encoding])

Version synchrone de fs.readFile. Renvoie le contenu du fichier nommé nom de fichier.

Si l'encodage est spécifié, cette fonction renvoie une chaîne. Sinon, il renvoie un tampon.

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

Question rapide, à quoi sert le tampon renvoyé dans la version synchrone de readFile? Si je lis un fichier de façon synchrone et ne passe aucun encodage, il imprime un tampon, comment puis-je l'utiliser? Je vous remercie.
codingbbq

12
J'ai eu de l'expérience avec cela récemment. Disons que notre tampon est data. if (Buffer.isBuffer( data){ result = data.toString('utf8'); }Nous avons maintenant converti le tampon en texte lisible. C'est bon pour lire un fichier en texte brut ou tester le fichier par rapport aux types de format. Je pourrais faire un essai / capture pour voir s'il s'agit d'un fichier JSON par exemple; mais uniquement après la conversion du tampon en texte. Regardez ici pour plus d'informations: nodejs.org/api/buffer.html
Logan

Aussi loin que je sache, les tampons sont des flux d'octets, et sont bons pour envoyer des données "morceau par morceau". Vous devez avoir vu que le tampon ressemble à quelque chose AF 42 F1. Très pratique pour la communication client-serveur-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
merci beaucoup, si j'avais 15 points, je voterais pour votre réponse :)
karaxuna

Bonjour, dans la première ligne de votre code function readContent(callback), est-ce callbackun mot réservé? Je veux dire, est-ce la façon standard d'implémenter des rappels pour vos fonctions personnalisées? Je viens de commencer à apprendre le nœud.
Amal Antony

3
Salut Amal. Le rappel est simplement l'argument passé à sa fonction, ce pourrait être eventou cou n'importe quel nom que vous aimez - ce n'est pas un mot réservé en Javascript, et je suppose que la même chose s'étend à Node.js.
RealDeal_EE'18

readContent(function (err, content)me donne une erreur de syntaxe lors de l'utilisation de la fonction comme paramètre.
monsto

66

Utilisation de promesses avec ES7

Utilisation asynchrone avec mz / fs

Le mzmodule fournit des versions promises de la bibliothèque de nœuds principaux. Leur utilisation est simple. Installez d'abord la bibliothèque ...

npm install mz

Ensuite...

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

Vous pouvez également les écrire dans des fonctions asynchrones:

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

6
c'est l'avenir et devrait être hautement voté par tout le monde :) merci
PirateApp

2
semble intéressant. Une faute de frappe: 'console.error (catch)' devrait être 'console.error (err)' je présume).
philwalk

2
Si vous ne voulez pas ajouter de package supplémentaire, essayez la solution de
@doctorlee

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

utilisez-le pour appeler un fichier de façon synchrone, sans encoder sa sortie affichée sous forme de tampon.


2
Vous avez besoin d'une ligne vierge avant les blocs de code pour que la jolie impression
démarre

briefé et le meilleur!
Diamond

13

Cette ligne fonctionnera,

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

1
7 ans ont passé :) fs.readFileSyncest une méthode de synchronisation, donc pas besoin de awaitlà. Await est utile avec les promesses ( nodejs.org/api/fs.html#fs_fs_promises_api ), lorsque vous voulez écrire du code asynchrone avec une syntaxe similaire au code de synchronisation.
karaxuna

@karaxuna, oui. supprimé. Je viens de rencontrer ce cas aujourd'hui et j'ai résolu en utilisant le code ci-dessus.
Aravin

1
Ceci est la réponse la plus simple. Si vous n'avez pas besoin d'async, pourquoi diable voudriez-vous mélanger avec la version async, avec des rappels, async / wait, etc?. C'est la voie à suivre.
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
S'il vous plaît, ne vous contentez pas de mettre du code dans votre réponse ... expliquez pourquoi il est différent et comment il résout le problème.
Studocwho

@doctorlee Cela fonctionne réellement pour moi, sans bibliothèque externe. Une explication est nécessaire à coup sûr.
Ashutosh Chamoli

7

synchroniser et asynchroniser la lecture des fichiers:

//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 Disponible sur read_file .


7

Comme dit, fs.readFilec'est une action asynchrone. Cela signifie que lorsque vous dites à node de lire un fichier, vous devez considérer que cela prendra un certain temps, et en attendant, node a continué à exécuter le code suivant. Dans votre cas, c'est:console.log(content); .

C'est comme envoyer une partie de votre code pour un long voyage (comme lire un gros fichier).

Jetez un œil aux commentaires que j'ai écrits:

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

C'est pourquoi contentest toujours vide lorsque vous vous connectez. le nœud n'a pas encore récupéré le contenu du fichier.

Cela pourrait être résolu en se déplaçant console.log(content)à l'intérieur de la fonction de rappel, juste après content = data;. De cette façon, vous verrez le journal lorsque le nœud aura fini de lire le fichier et après contentobtiendra une valeur.


6

Utilisez la bibliothèque promisify intégrée (Node 8+) pour rendre ces anciennes fonctions de rappel plus élégantes.

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

Peut être en une seule ligne const doStuff = async (filePath) => fs.readFileSync(filePath, 'utf8');, pas besoin d'envelopper l'utilitaire.
rab

1
Ne pas utiliser la version de synchronisation est le point de cela, et vous devriez gérer les erreurs lors de son appel
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);

C'est juste parce que le nœud est asynchrone et qu'il n'attendra pas la fonction de lecture et dès que le programme démarre, il consolidera la valeur comme non définie, ce qui est en fait vrai car aucune valeur n'est attribuée à la variable de contenu. Pour gérer, nous pouvons utiliser des promesses, des générateurs, etc. Nous pouvons utiliser la promesse de cette manière.

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

La fonction suivante fonctionnerait pour les chaînes d' asyncenroulement ou de promessethen

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

1

vous pouvez lire le fichier en

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

En plus, vous pouvez écrire dans un fichier,

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

et même l'enchaîner

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

Pour le dire en gros, vous avez affaire à node.js qui est de nature asynchrone.

Lorsque nous parlons d'async, nous parlons de faire ou de traiter des informations ou des données tout en traitant autre chose. Il n'est pas non plus parallèle, veuillez le rappeler.

Votre code:

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

Avec votre échantillon, il fait d'abord la partie console.log, donc la variable 'content' n'est pas définie.

Si vous voulez vraiment la sortie, faites quelque chose comme ceci à la place:

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

C'est asynchrone. Il sera difficile de s'y habituer mais, c'est ce que c'est. Encore une fois, c'est une explication grossière mais rapide de ce qu'est l'async.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.