Dapatkan data dari fs.readFile

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

Log undefined, kenapa?

karaxuna
sumber
1
fs.readFileSync juga memiliki fitur keren untuk membaca file walaupun dalam format unfode utf8.
Praneeth
NB fs.readFile juga dapat melakukannya ^ lihat jawaban saya di bawah
Dominic

Jawaban:

348

Untuk menguraikan apa yang dikatakan @Raynos, fungsi yang telah Anda tetapkan adalah panggilan balik yang tidak sinkron. Itu tidak langsung dieksekusi, melainkan dieksekusi ketika memuat file telah selesai. Ketika Anda memanggil readFile, kontrol segera dikembalikan dan baris kode berikutnya dijalankan. Jadi ketika Anda memanggil console.log, callback Anda belum dipanggil, dan konten ini belum disetel. Selamat datang di pemrograman asinkron.

Contoh pendekatan

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

Atau lebih baik lagi, seperti ditunjukkan oleh contoh Raynos, bungkus panggilan Anda dalam suatu fungsi dan sampaikan panggilan balik Anda sendiri. (Rupanya ini adalah praktik yang lebih baik) Saya pikir membiasakan diri untuk membungkus panggilan async Anda dalam fungsi yang mengambil panggilan balik akan menghemat banyak masalah dan kode berantakan.

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

doSomething (function doSomethingAfter(err, result) {
    // process the async result
});
Matt Esch
sumber
2
Sinkronisasi I / O memiliki tempatnya - tidak masalah jika Anda melakukan sistem atau alat build kecil. Pada sistem yang lebih besar atau aplikasi server, praktik terbaik adalah menghindarinya.
RobW
28
Tidak semuanya server web. Dan tidak ada yang mengerikan tentang mengerikan tentang menggunakan versi sinkronisasi metode untuk satu panggilan panggilan sebelum server mulai menerima permintaan. Siapa pun yang menggunakan Node harus benar-benar mengerti mengapa sebelum menggunakannya. Pasti sebelum kata-kata kasar tentang blogging.
Erik Reppen
7
Anda harus memasukkan 'utf8'setelah nama file sebagai parameter tambahan, jika tidak, ia hanya akan mengembalikan buffer. Lihat: stackoverflow.com/questions/9168737/…
DollarAkshay
252

Sebenarnya ada fungsi Sinkron untuk ini:

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

Tidak sinkron

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

Secara sinkron membaca seluruh isi file. Contoh:

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

Panggilan balik dilewatkan dua argumen (err, data), di mana data adalah isi file.

Jika tidak ada pengkodean yang ditentukan, maka buffer mentah dikembalikan.


SINKRONIS

fs.readFileSync(filename, [encoding])

Versi sinkron dari fs.readFile. Mengembalikan konten file bernama nama file.

Jika pengkodean ditentukan maka fungsi ini mengembalikan sebuah string. Kalau tidak, ia mengembalikan buffer.

var text = fs.readFileSync('test.md','utf8')
console.log (text)
Logan
sumber
Pertanyaan cepat, apa gunanya buffer yang dikembalikan dalam versi sinkron dari readFile? Jika saya membaca file secara sinkron dan tidak lulus encoding apa pun, ia mencetak buffer, bagaimana saya bisa menggunakan ini? Terima kasih.
codingbbq
12
Saya memiliki pengalaman dengan ini baru-baru ini. Katakanlah buffer kita data. if (Buffer.isBuffer( data){ result = data.toString('utf8'); }Sekarang kami telah mengubah buffer menjadi teks yang dapat dibaca. Ini bagus untuk membaca file plaintext atau menguji file terhadap tipe format. Saya bisa mencoba / menangkap untuk melihat apakah itu file JSON misalnya; tetapi hanya setelah buffer dikonversi menjadi teks. Lihat di sini untuk informasi lebih lanjut: nodejs.org/api/buffer.html
Logan
Sejauh yang saya tahu buffer adalah aliran oktet, dan bagus untuk mengirim data "sepotong demi sepotong." Anda pasti sudah melihat bahwa buffer itu seperti AF 42 F1. Sangat praktis untuk komunikasi klien-server-klien.
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
sumber
6
terima kasih banyak, jika saya memiliki 15 nilai, saya akan memilih jawaban Anda :)
karaxuna
Hai, di baris pertama kode Anda function readContent(callback),, apakah callbackkata yang dilindungi undang-undang? Maksud saya, apakah ini cara standar untuk menerapkan panggilan balik untuk fungsi kustom Anda? Saya baru saja mulai belajar simpul.
Amal Antony
3
Hai Amal. Callback hanyalah argumen yang diteruskan ke fungsinya, bisa saja eventatau catau nama apa pun yang Anda suka - itu bukan kata yang dilindungi undang-undang dalam Javascript, dan saya akan menganggapnya meluas ke Node.js.
RealDeal_EE'18
readContent(function (err, content)memberi saya kesalahan sintaks saat menggunakan fungsi sebagai parameter.
monsto
66

Menggunakan Janji dengan ES7

Penggunaan asinkron dengan mz / fs

The mzmodul menyediakan versi promisified perpustakaan inti simpul. Menggunakannya sederhana. Pertama instal perpustakaan ...

npm install mz

Kemudian...

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

Atau Anda dapat menuliskannya dalam fungsi asinkron:

async function myReadfile () {
  try {
    const file = await fs.readFile('./Index.html');
  }
  catch (err) { console.error( err ) }
};
Evan Carroll
sumber
6
ini adalah masa depan dan harus sangat dijunjung tinggi oleh semua orang :) terima kasih
PirateApp
2
terlihat menarik. Satu kesalahan ketik: 'console.error (catch)' harus 'console.error (err)' Saya kira).
philwalk
2
Jika Anda tidak ingin menambahkan paket tambahan, coba solusi @doctorlee di bawah ini
rahuljain1311
18
var data = fs.readFileSync('tmp/reltioconfig.json','utf8');

gunakan ini untuk memanggil file secara sinkron, tanpa menyandiaksikan output yang ditampilkan sebagai buffer.

pengguna2266928
sumber
2
Anda memerlukan baris kosong sebelum blok kode agar pencetakan cantik dapat
dimulai
briefing & yang terbaik!
Diamond
13

Baris ini akan bekerja,

const content = fs.readFileSync('./Index.html', 'utf8');
console.log(content);
Aravin
sumber
1
7 tahun berlalu :) fs.readFileSyncadalah metode sinkronisasi, jadi tidak perlu di awaitsana. Menunggu berguna dengan janji-janji ( simpuljs.org/api/fs.html#fs_fs_promises_api ), ketika Anda ingin menulis kode async dengan sintaksis yang mirip dengan kode sinkronisasi.
karaxuna
@karaxuna, ya. dihapus. Saya baru saja menemukan kasus ini hari ini & saya menyelesaikan menggunakan kode di atas.
Aravin
1
Ini jawaban paling sederhana. Jika Anda tidak membutuhkan async, mengapa Anda harus bergaul dengan versi async sama sekali, dengan panggilan balik, async / menunggu, dll? Ini cara untuk pergi.
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!");
      });
    });
  }
dokter
sumber
5
Tolong jangan hanya memasukkan kode dalam jawaban Anda ... jelaskan mengapa itu berbeda dan bagaimana memecahkan masalah.
Studocwho
@ doctorlee Ini sebenarnya bekerja untuk saya, tanpa perpustakaan eksternal. Penjelasan diperlukan untuk memastikan.
Ashutosh Chamoli
7

sinkronisasi dan cara membaca file async:

//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 Tersedia di read_file .

Zeeshan Hassan Memon
sumber
7

Seperti yang dikatakan, fs.readFileadalah tindakan asinkron. Ini berarti bahwa ketika Anda memberi tahu node untuk membaca file, Anda perlu mempertimbangkan bahwa itu akan memakan waktu, dan sementara itu, node terus menjalankan kode berikut. Dalam kasus Anda itu: console.log(content);.

Ini seperti mengirim beberapa bagian dari kode Anda untuk perjalanan panjang (seperti membaca file besar).

Lihatlah komentar yang saya tulis:

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

Itu sebabnya contentmasih kosong saat Anda login. node belum mengambil konten file.

Ini bisa diatasi dengan bergerak console.log(content)di dalam fungsi panggilan balik, tepat setelah itu content = data;. Dengan cara ini Anda akan melihat log ketika simpul selesai membaca file dan setelah contentmendapat nilai.

Taitu-lism
sumber
6

Gunakan pustaka promisifikasi bawaan (Node 8+) untuk membuat fungsi-fungsi panggilan balik yang lama ini lebih elegan.

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
sumber
Bisa dalam satu baris const doStuff = async (filePath) => fs.readFileSync(filePath, 'utf8');, tidak perlu bungkus utilisasi.
rab
1
Tidak menggunakan versi sinkronisasi adalah hal ini, dan Anda harus menangani kesalahan saat memanggilnya
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
sumber
2
var content;
fs.readFile('./Index.html', function read(err, data) {
    if (err) {
        throw err;
    }
    content = data;
});
console.log(content);

Ini hanya karena simpul tidak sinkron dan tidak akan menunggu fungsi baca dan segera setelah program dimulai akan menghibur nilai sebagai tidak terdefinisi, yang sebenarnya benar karena tidak ada nilai yang ditetapkan ke variabel konten. Untuk mengatasinya kita bisa menggunakan janji, generator, dll. Kita bisa menggunakan janji dengan cara ini.

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.
})
Diluman Nouman
sumber
2

Berikut ini adalah fungsi yang akan bekerja untuk rantai asyncbungkus atau janjithen

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

Anda dapat membaca file dengan

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

Menambahkan pada Anda dapat menulis ke file,

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

dan bahkan rantai itu bersama

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
sumber
1

Secara kasar, Anda berurusan dengan node.js yang sifatnya tidak sinkron.

Ketika kita berbicara tentang async, kita berbicara tentang melakukan atau memproses informasi atau data saat berurusan dengan sesuatu yang lain. Itu tidak identik dengan paralel, harap diingatkan.

Kode Anda:

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

Dengan sampel Anda, itu pada dasarnya melakukan bagian console.log terlebih dahulu, sehingga variabel 'konten' tidak terdefinisi.

Jika Anda benar-benar menginginkan hasilnya, lakukan sesuatu seperti ini sebagai gantinya:

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

Ini tidak sinkron. Akan sulit untuk membiasakan diri, tetapi ini adalah apa adanya. Sekali lagi, ini adalah penjelasan kasar tapi cepat tentang apa itu async.

DayIsGreen
sumber