Отримати дані з fs.readFile


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

Логи undefined, чому?


1
fs.readFileSync також має цікаві функції для читання файлу, навіть якщо він є у форматі unicode utf8.
Пранієт

NB fs.readFile також може це зробити ^ дивіться мою відповідь нижче
Домінік

Відповіді:


347

Щоб детальніше розповісти про те, що сказав @Raynos, визначена вами функція - це асинхронний зворотний зв'язок. Він не виконується відразу, скоріше він виконується, коли завантаження файлів завершено. Коли ви викликаєте readFile, керування повертається негайно і виконується наступний рядок коду. Тож, коли ви телефонуєте console.log, ваш зворотний дзвінок ще не викликався, і цей вміст ще не встановлений. Ласкаво просимо до асинхронного програмування.

Приклад підходів

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

Або ще краще, як показує приклад Raynos, переключіть свій дзвінок у функцію та передайте власні зворотні дзвінки. (Мабуть, це є кращою практикою). Я думаю, що звичка впакувати асинхронні дзвінки у функцію, яка приймає зворотний виклик, заощадить вам багато клопоту та безладного коду.

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

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

2
Синхронізація вводу / виводу має своє місце - це добре, якщо ви робите невелику систему збирання або інструмент. У великих системах або серверних додатках найкращою практикою є уникати цього.
RobW

27
Не все - це веб-сервер. І нічого страшного в тому, що використовувати версії методів синхронізації для однократних дзвінків, перш ніж сервер почав приймати запити, немає нічого страшного. Кожен, хто використовує Node, повинен дійсно зрозуміти, чому до цього користуватися. Безумовно, перш ніж рент-блог про це.
Ерік Реппен


7
Ви повинні включити 'utf8'після імені файлу як додатковий параметр, інакше він просто поверне буфер. Див: stackoverflow.com/questions/9168737 / ...
DollarAkshay

252

Насправді для цього є функція синхронізації:

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

Асинхронний

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

Асинхронно читає весь вміст файлу. Приклад:

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

У зворотний виклик передаються два аргументи (помилка, дані), де дані є вмістом файла.

Якщо кодування не вказано, то необроблений буфер повертається.


СИНХРОННО

fs.readFileSync(filename, [encoding])

Синхронна версія fs.readFile. Повертає вміст файлу з ім'ям файлу.

Якщо вказано кодування, ця функція повертає рядок. В іншому випадку він повертає буфер.

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

Швидке запитання, в чому полягає використання буфера, який повертається в синхронній версії readFile? Якщо я читаю файл синхронно і не пропускаю жодного кодування, він друкує буфер, як я можу це використовувати? Дякую.
codingbbq

12
Я з цим нещодавно мав досвід. Скажімо, наш буфер є data. if (Buffer.isBuffer( data){ result = data.toString('utf8'); }Тепер ми перетворили буфер в читаний текст. Це добре для того, щоб прочитати файл простого тексту або протестувати файл на типи формату. Я можу зробити спробу / зловити, щоб побачити, чи це, наприклад, файл JSON; але лише після перетворення буфера в текст. Подивіться тут для отримання додаткової інформації: nodejs.org/api/buffer.html
Логан

Крім того, наскільки я знаю, буфери - це октетні потоки, і вони хороші для надсилання даних "по частинах". Напевно, ви бачили, що буфер - це щось на кшталт AF 42 F1. Дуже практично для спілкування клієнт-сервер-клієнт.
Логан

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
велике спасибі, якби у мене було 15 балів, я би проголосував за вашу відповідь :)
karaxuna

Привіт, у першому рядку вашого коду function readContent(callback)є callbackзарезервоване слово? Я маю на увазі, це стандартний спосіб реалізовувати зворотні дзвінки для своїх спеціальних функцій? Я тільки почав вивчати вузол.
Амаль Антоній

3
Привіт Амаль. Зворотний виклик - це просто аргумент, переданий його функції, це може бути eventабо cбудь-яке ім'я, яке вам подобається - це не зарезервоване слово в Javascript, і я вважаю, що те саме поширюється на Node.js.
RealDeal_EE'18

readContent(function (err, content)дає мені синтаксичну помилку при використанні функції в якості параметра.
Монсто

66

Використання обіцянок із ES7

Асинхронне використання з mz / fs

mzМодуль забезпечує promisified версії бібліотеки ядра вузла. Використовувати їх просто. Спочатку встановіть бібліотеку ...

npm install mz

Тоді...

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

Можна також записати їх в асинхронних функціях:

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

6
це майбутнє, і його повинні всіляко оцінити :) дякую
PirateApp

2
виглядає цікаво. Один помилка: 'console.error (catch)' має бути 'console.error (помилка)' я припускаю).
фольклор

2
Якщо ви не хочете додавати додатковий пакет, спробуйте рішення
@doctorlee

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

використовувати це для синхронного виклику файлу, не кодуючи його показ виводу як буфера.


2
Вам потрібен порожній рядок перед кодовими блоками, щоб почати гарненьке друкування.
royhowie

ознайомлено & найкраще!
Алмаз

12

Ця лінія буде працювати,

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

1
Пройшло 7 років :) fs.readFileSync- це метод синхронізації, тому в цьому немає потреби await. Чекайте корисного з обіцянками ( nodejs.org/api/fs.html#fs_fs_promises_api ), коли ви хочете написати асинхронний код із синтаксисом, подібним до коду синхронізації.
karaxuna

@karaxuna, так. вилучено. Я просто натрапив на цей випадок сьогодні, і я вирішив за допомогою наведеного вище коду.
Аравін

1
Це найпростіша відповідь. Якщо вам не потрібна асинхронізація, чому б у світі ви взагалі змішувались з версією async, з зворотними дзвінками, асинхронізацією / очікуванням тощо? Це шлях.
Майстер качок

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
Будь ласка, не проставляйте код у своїй відповіді ... поясніть, чому він різний і як він вирішує проблему.
Studocwho

@doctorlee Це насправді працює для мене без жодної зовнішньої бібліотеки. Пояснення потрібно точно.
Ашутош Шамолі

7

синхронізація та асинхронізація способу читання файлів:

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

Чіт для вузлів Доступний у read_file .


7

Як було сказано, fs.readFileце асинхронна дія. Це означає, що коли ви кажете вузлу прочитати файл, вам потрібно врахувати, що це пройде певний час, а тим часом вузол продовжує виконувати наступний код. У вашому випадку це:console.log(content); .

Це як надіслати частину коду в далеку поїздку (наприклад, читання великого файлу).

Погляньте на коментарі, які я написав:

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

Ось чому content він все ще порожній, коли ви реєструєте його. вузол ще не знайшов вміст файлу.

Це можна вирішити, перемістившись console.log(content)всередину функції зворотного виклику, відразу після content = data;. Таким чином ви побачите журнал, коли вузол буде прочитаний файл і після contentотримає значення.


6

Використовуйте вбудовану бібліотеку для багатообіцяючих даних (вузол 8+), щоб зробити ці старі функції зворотного виклику більш елегантними.

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

Може бути в одному рядку const doStuff = async (filePath) => fs.readFileSync(filePath, 'utf8');, не потрібно util.promisify wrap.
раб

1
Справа в цьому не в тому, щоб використовувати версію синхронізації, і вам слід керувати помилками при її виклику
Домінік

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

Це лише тому, що вузол є асинхронним, і він не чекатиме функції зчитування, і як тільки програма запустить, він консолірує значення як невизначене, що насправді відповідає дійсності, оскільки значення змінній змісту не присвоєно. Для обробки ми можемо використовувати обіцянки, генератори тощо. Ми можемо використовувати обіцянку таким чином.

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

Далі йде функція, яка буде працювати для asyncобгортання або обіцянки thenланцюгів

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

1

ви можете прочитати файл

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

Додавши, ви можете написати у файл,

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

і навіть ланцюжок разом

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

Якщо говорити приблизно так, ви маєте справу з node.js, який має асинхронний характер.

Коли ми говоримо про асинхронізацію, ми говоримо про те, як робити чи обробляти інформацію чи дані, займаючись чимось іншим. Паралель не є синонімом паралелі, нагадайте.

Ваш код:

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

З вашим зразком це, по суті, робить частину console.log спочатку, таким чином змінна 'content' не визначається.

Якщо ви дійсно хочете вихід, зробіть щось подібне замість цього:

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

Це асинхронно. До цього важко буде звикнути, але воно є. Знову ж таки, це грубе, але швидке пояснення, що таке асинхроніка.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.