อ่านไฟล์ข้อความโดยใช้ Node.js?


124

ฉันต้องส่งไฟล์ข้อความในเทอร์มินัลจากนั้นอ่านข้อมูลจากไฟล์ฉันจะทำอย่างไร

node server.js file.txt

ฉันจะผ่านเส้นทางจากอาคารผู้โดยสารได้อย่างไรฉันจะอ่านอีกด้านหนึ่งได้อย่างไร


หากคุณพบว่าตัวเองเพิ่มตัวเลือกมากขึ้นในบรรทัดคำสั่งคุณสามารถใช้Optimist
เจส

stackoverflow.com/questions/6156501/…แสดงอีกวิธีหนึ่งในการอ่านไฟล์ข้อความ
Marc Durdin

คำตอบ:


172

คุณจะต้องใช้process.argvอาร์เรย์เพื่อเข้าถึงอาร์กิวเมนต์บรรทัดคำสั่งเพื่อรับชื่อไฟล์และโมดูล FileSystem (fs)เพื่ออ่านไฟล์ ตัวอย่างเช่น:

// Make sure we got a filename on the command line.
if (process.argv.length < 3) {
  console.log('Usage: node ' + process.argv[1] + ' FILENAME');
  process.exit(1);
}
// Read the file and print its contents.
var fs = require('fs')
  , filename = process.argv[2];
fs.readFile(filename, 'utf8', function(err, data) {
  if (err) throw err;
  console.log('OK: ' + filename);
  console.log(data)
});

ในการแยกย่อยออกไปเล็กน้อยสำหรับคุณprocess.argvมักจะมีความยาว 2 รายการ zeroth เป็นตัวแปล "โหนด" และรายการแรกคือสคริปต์ที่โหนดกำลังทำงานอยู่รายการหลังจากนั้นจะถูกส่งต่อในบรรทัดคำสั่ง เมื่อคุณดึงชื่อไฟล์จาก argv แล้วคุณสามารถใช้ฟังก์ชันระบบไฟล์เพื่ออ่านไฟล์และทำอะไรก็ได้ที่คุณต้องการกับเนื้อหา ตัวอย่างการใช้งานจะมีลักษณะดังนี้:

$ node ./cat.js file.txt
OK: file.txt
This is file.txt!

[แก้ไข]ตามที่ @wtfcoder กล่าวถึงการใช้fs.readFile()เมธอด "" อาจไม่ใช่ความคิดที่ดีที่สุดเพราะจะบัฟเฟอร์เนื้อหาทั้งหมดของไฟล์ก่อนที่จะให้ฟังก์ชันเรียกกลับ การบัฟเฟอร์นี้อาจใช้หน่วยความจำจำนวนมาก แต่ที่สำคัญกว่านั้นไม่ได้ใช้ประโยชน์จากหนึ่งในคุณสมบัติหลักของ node.js - asynchronous, evented I / O

วิธี "โหนด" ในการประมวลผลไฟล์ขนาดใหญ่ (หรือไฟล์ใด ๆ จริงๆ) คือการใช้fs.read()และประมวลผลแต่ละส่วนที่มีอยู่ตามที่มีอยู่ในระบบปฏิบัติการ อย่างไรก็ตามการอ่านไฟล์ในลักษณะนี้คุณจะต้องทำการแยกวิเคราะห์ / ประมวลผลไฟล์แบบเพิ่มหน่วยของคุณเอง (อาจเป็น) และการบัฟเฟอร์จำนวนหนึ่งอาจหลีกเลี่ยงไม่ได้


ยอดเยี่ยมขอบคุณมากมีประโยชน์มาก ฉันจะแยกข้อมูลนี้ทีละบรรทัดได้อย่างไร
แฟนซี

10
@fancy: ลองvar lines = data.split(/\r?\n/);แล้วอาร์เรย์ "เส้น" จะมีแต่ละบรรทัด
maerics

1
นี่ไม่ใช่ความคิดที่ดีหากไฟล์ข้อความมีขนาดใหญ่เนื่องจากจะถูกอ่านทั้งหมดในหน่วยความจำหากคุณประมวลผลว่าไฟล์ CSV ขนาด 1,000 เมกะไบต์ดูที่ fs.createFilestream คุณจะต้องดูแลด้วยการแยกบรรทัดแม้ว่าจะเป็นส่วนข้อมูลก็ตาม เคยชิน (ในกรณีส่วนใหญ่) ตกอยู่ในขอบเขตของเส้น (บางคนได้คิดวิธีแก้ปัญหาแล้ว - Google)
MâttFrëëman

1
@wtfcoder: ใช่จุดที่ดีมาก จุดประสงค์ของฉันเพียงเพื่อแสดงให้เห็นถึงกรณีง่ายๆของการอ่านไฟล์ที่มีชื่อบนบรรทัดคำสั่ง เห็นได้ชัดว่ามีรายละเอียดปลีกย่อยมากมาย (โดยเฉพาะประสิทธิภาพ) ที่อยู่นอกเหนือขอบเขตของคำถามนี้
maerics

ฉันโพสต์วิธีแก้ปัญหาสำหรับคำถามที่คล้ายกันสำหรับการแยกวิเคราะห์ไฟล์ขนาดใหญ่โดยใช้สตรีมซิงโครนัส ดู: stackoverflow.com/questions/16010915/…
เจอราร์ด

35

ใช้ fs กับโหนด

var fs = require('fs');

try {  
    var data = fs.readFileSync('file.txt', 'utf8');
    console.log(data.toString());    
} catch(e) {
    console.log('Error:', e.stack);
}

โปรดทราบว่านี่เป็นเวอร์ชันซิงโครนั
Rich Werden

@RichWerden คำว่า "ซิงโครนัส" ในบริบทนี้หมายถึงอะไร
Json

1
ในโหนดเมื่อมีบางสิ่ง "ซิงโครนัส" ระบบจะหยุด / บล็อกระบบไม่ให้ทำสิ่งอื่นใด สมมติว่าคุณมีเว็บเซิร์ฟเวอร์โหนดหากมีคำขออื่นเข้ามาในขณะที่เกิดเหตุการณ์ข้างต้นเซิร์ฟเวอร์จะไม่ / ไม่สามารถตอบสนองได้เนื่องจากไม่ว่างในการอ่านไฟล์
Rich Werden

27

fs.readFile()ควรหลีกเลี่ยงIMHO เนื่องจากโหลดไฟล์ทั้งหมดในหน่วยความจำและจะไม่เรียกการเรียกกลับจนกว่าไฟล์ทั้งหมดจะถูกอ่าน

วิธีที่ง่ายที่สุดในการอ่านไฟล์ข้อความคือการอ่านทีละบรรทัด ฉันแนะนำBufferedReader :

new BufferedReader ("file", { encoding: "utf8" })
    .on ("error", function (error){
        console.log ("error: " + error);
    })
    .on ("line", function (line){
        console.log ("line: " + line);
    })
    .on ("end", function (){
        console.log ("EOF");
    })
    .read ();

สำหรับโครงสร้างข้อมูลที่ซับซ้อนเช่นไฟล์. คุณสมบัติหรือ json คุณต้องใช้ parser (ภายในควรใช้ตัวอ่านบัฟเฟอร์ด้วย)


7
ขอขอบคุณที่ชี้ให้เห็นเทคนิคนี้ คุณคิดถูกว่านี่อาจเป็นวิธีที่ดีที่สุด แต่ฉันแค่คิดว่ามันสับสนเล็กน้อยในบริบทของคำถามนี้ซึ่งฉันคิดว่ากำลังถามเกี่ยวกับกรณีการใช้งานที่ไม่ต้องการมาก ดังที่ได้ระบุไว้ข้างต้นหากเป็นเพียงไฟล์ขนาดเล็กที่ถูกส่งไปยังเครื่องมือบรรทัดคำสั่งก็ไม่มีเหตุผลที่จะไม่ใช้fs.readFile()หรือfs.readFileSync(). มันต้องเป็นไฟล์ขนาดใหญ่ที่ทำให้ต้องรออย่างเห็นได้ชัด ไฟล์ config JSON เช่น package.json มีแนวโน้มที่จะต่ำกว่า 1 กิโลเพื่อให้คุณสามารถเพียงfs.readFile()และJSON.parse()มัน
John Starr Dewar

1
BufferedReader อาจเปลี่ยนลายเซ็น ฉันต้องแทนที่ BufferedReader ด้วย BufferedReader, DataReader โดยที่ BufferedReader เป็นโมดูล ดูgithub.com/Gagle/Node-BufferedReader
bnieland

13
ฉันเห็นว่าตอนนี้ BufferedReader เลิกใช้งานแล้ว
Marc Rochkind

6

คุณสามารถใช้ readstream และ pipe เพื่ออ่านไฟล์ทีละบรรทัดโดยไม่ต้องอ่านไฟล์ทั้งหมดในหน่วยความจำเพียงครั้งเดียว

var fs = require('fs'),
    es = require('event-stream'),
    os = require('os');

var s = fs.createReadStream(path)
    .pipe(es.split())
    .pipe(es.mapSync(function(line) {
        //pause the readstream
        s.pause();
        console.log("line:", line);
        s.resume();
    })
    .on('error', function(err) {
        console.log('Error:', err);
    })
    .on('end', function() {
        console.log('Finish reading.');
    })
);

5

ฉันกำลังโพสต์ตัวอย่างที่สมบูรณ์ซึ่งในที่สุดฉันก็ได้ผล ที่นี่ฉันกำลังอ่านไฟล์rooms/rooms.txtจากสคริปต์rooms/rooms.js

var fs = require('fs');
var path = require('path');
var readStream = fs.createReadStream(path.join(__dirname, '../rooms') + '/rooms.txt', 'utf8');
let data = ''
readStream.on('data', function(chunk) {
    data += chunk;
}).on('end', function() {
    console.log(data);
});
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.