รับข้อมูลจาก 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
Praneeth

NB fs.readFile ยังสามารถทำเช่นนั้น ^ ดูคำตอบของฉันด้านล่าง
โดมินิ

คำตอบ:


348

หากต้องการอธิบายรายละเอียดเกี่ยวกับสิ่งที่ @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 แสดงให้เห็นห่อสายของคุณในฟังก์ชั่นและผ่านในการเรียกกลับของคุณเอง (เห็นได้ชัดว่านี่เป็นวิธีปฏิบัติที่ดีกว่า) ฉันคิดว่าการใช้งานการโทรแบบ async ของคุณเป็นสิ่งที่ใช้ในการโทรกลับจะช่วยให้คุณประหยัดปัญหาและรหัสยุ่งได้

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

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

2
Sync I / O มีที่ตั้ง - มันใช้ได้ดีถ้าคุณกำลังสร้างระบบหรือเครื่องมือเล็ก ๆ ในระบบที่ใหญ่กว่าหรือแอปเซิร์ฟเวอร์แนวปฏิบัติที่ดีที่สุดคือหลีกเลี่ยง
RobW

27
ไม่ใช่ทุกอย่างที่เป็นเว็บเซิร์ฟเวอร์ และไม่มีอะไรน่ากลัวเกี่ยวกับการใช้วิธีการซิงค์รุ่นสำหรับการโทรครั้งเดียวก่อนที่เซิร์ฟเวอร์จะเริ่มทำการร้องขอ ใครก็ตามที่ใช้โหนดควรเข้าใจว่าทำไมก่อนที่จะใช้มัน แน่นอนก่อนที่จะคุยโวเกี่ยวกับเรื่องนี้
Erik Reppen


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

การเรียกกลับถูกส่งผ่านสองอาร์กิวเมนต์ (err, data) โดยที่ data คือเนื้อหาของไฟล์

หากไม่ได้ระบุการเข้ารหัสไว้บัฟเฟอร์ดิบจะถูกส่งกลับ


พร้อมกัน

fs.readFileSync(filename, [encoding])

รุ่นซิงโครนัสของ fs.readFile ส่งคืนเนื้อหาของไฟล์ชื่อ filename

หากระบุการเข้ารหัสแล้วฟังก์ชันนี้จะส่งคืนสตริง มิฉะนั้นจะส่งคืนบัฟเฟอร์

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
Logan

นอกจากนี้เท่าที่ฉันรู้บัฟเฟอร์เป็นกระแส octet และดีสำหรับการส่งข้อมูล "ทีละชิ้น" 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คำสงวน? ฉันหมายความว่านี่เป็นวิธีมาตรฐานในการใช้การเรียกกลับสำหรับฟังก์ชันที่กำหนดเองของคุณหรือไม่ ฉันเพิ่งเริ่มเรียนรู้โหนด
Amal Antony

3
สวัสดี Amal การเรียกกลับเป็นเพียงข้อโต้แย้งที่ส่งผ่านไปยังฟังก์ชั่นของเขาอาจเป็นeventหรือcหรือชื่อใดก็ได้ที่คุณชอบ - ไม่ใช่คำสงวนใน Javascript และฉันจะถือว่าเป็นแบบเดียวกันกับ Node.js
RealDeal_EE'18

readContent(function (err, content)ทำให้ฉันมีข้อผิดพลาดทางไวยากรณ์เมื่อใช้ฟังก์ชั่นเป็นพารามิเตอร์
monsto

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 (err)' ฉันเข้าใจ)
philwalk

2
หากคุณไม่ต้องการที่จะเพิ่มแพคเกจพิเศษลองวิธีแก้ปัญหาของ
@doctorlee

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

ใช้สิ่งนี้เพื่อเรียกไฟล์แบบซิงโครนัสโดยไม่ต้องเข้ารหัสเอาต์พุตที่แสดงเป็นบัฟเฟอร์


2
คุณต้องมีบรรทัดว่างก่อนโค้ดบล็อกเพื่อให้การพิมพ์ออกมาสวย
royhowie

ฟังการบรรยายสรุปและที่ดีที่สุด!
Diamond

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 ) เมื่อคุณต้องการเขียนโค้ด async ด้วยไวยากรณ์ที่คล้ายกับรหัสซิงค์
karaxuna

@ Karaxuna ใช่ ลบออก ฉันเพิ่งเจอเคสนี้วันนี้ & ฉันแก้ไขโดยใช้โค้ดด้านบน
Aravin

1
นี่คือคำตอบที่ง่ายที่สุด หากคุณไม่ต้องการใช้ async ทำไมคุณถึงต้องผสมกับรุ่น async เลยด้วย callback, async / await เป็นต้น นี่คือวิธีที่จะไป
อาจารย์เป็ด

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 มันใช้งานได้จริงสำหรับฉันโดยไม่ต้องมีห้องสมุดภายนอก ต้องมีการอธิบายอย่างแน่นอน
Ashutosh Chamoli

7

วิธีการอ่านซิงค์และไฟล์ 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);

โหนดโกงว่างที่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

ใช้ไลบรารี promisify ในตัว (โหนด 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');โดยไม่จำเป็นต้องใช้
rab

1
ไม่ได้ใช้รุ่นซิงค์เป็นจุดนี้และคุณควรจะจัดการกับข้อผิดพลาดในการเรียกมันว่า
โดมินิก


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 ซึ่งเป็นแบบอะซิงโครนัสในธรรมชาติ

เมื่อเราพูดถึง async เรากำลังพูดถึงการทำหรือประมวลผลข้อมูลหรือข้อมูลในขณะที่จัดการกับสิ่งอื่น มันไม่ได้หมายถึงขนานกันโปรดได้รับการเตือน

รหัสของคุณ:

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

ด้วยตัวอย่างของคุณโดยทั่วไปแล้วมันจะทำการ console.log ส่วนแรกจึงทำให้ตัวแปร 'เนื้อหา' ไม่ได้กำหนด

หากคุณต้องการเอาท์พุทให้ทำสิ่งนี้แทน:

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

นี่คืออะซิงโครนัส มันจะยากที่จะชินกับมัน แต่มันคือสิ่งที่มันเป็น อีกครั้งนี่เป็นคำอธิบายคร่าวๆ แต่อย่างรวดเร็วสำหรับ async คืออะไร

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.