如何在Nodejs中使用模塊fs文件系統(tǒng)
概述
node 的fs文檔密密麻麻的 api 非常多,畢竟全面支持對(duì)文件系統(tǒng)的操作。文檔組織的很好,操作基本分為文件操作、目錄操作、文件信息、流這個(gè)大方面,編程方式也支持同步、異步和 Promise。
本文記錄了幾個(gè)文檔中沒(méi)詳細(xì)描寫(xiě)的問(wèn)題,可以更好地串聯(lián)fs文檔思路:
- 文件描述符
- 同步、異步與 Promise
- 目錄與目錄項(xiàng)
- 文件信息
- stream
文件描述符
文件描述符是一個(gè)非負(fù)整數(shù)。它是一個(gè)索引值,操作系統(tǒng)可以根據(jù)它來(lái)找到對(duì)應(yīng)的文件。
在 fs 的很多底層 api 中,需要用到文件描述符。在文檔中,描述符通常用fd來(lái)代表。例如:fs.read(fd, buffer, offset, length, position, callback)。與這個(gè) api 相對(duì)應(yīng)的是:fs.readFile(path[, options], callback)。
因?yàn)椴僮飨到y(tǒng)對(duì)文件描述符的數(shù)量有限制,因此在結(jié)束文件操作后,別忘記 close:
const fs = require("fs");
fs.open("./db.json", "r", (err, fd) => {
if (err) throw err;
// 文件操作...
// 完成操作后,關(guān)閉文件
fs.close(fd, err => {
if (err) throw err;
});
});
同步、異步與 Promise
所有文件系統(tǒng)的 api 都有同步和異步兩種形式。
同步寫(xiě)法
不推薦使用同步 api,會(huì)阻塞線程。
try {
const buf = fs.readFileSync("./package.json");
console.log(buf.toString("utf8"));
} catch (error) {
console.log(error.message);
}
異步寫(xiě)法
異步寫(xiě)法寫(xiě)起來(lái)容易進(jìn)入回調(diào)地獄。
fs.readFile("./package.json", (err, data) => {
if (err) throw err;
console.log(data.toString("utf8"));
});
(推薦)Promise 寫(xiě)法
在 node v12 之前,需要自己借助 promise 封裝:
function readFilePromise(path, encoding = "utf8") {
const promise = new Promise((resolve, reject) => {
fs.readFile(path, (err, data) => {
if (err) return reject(err);
return resolve(data.toString(encoding));
});
});
return promise;
}
readFilePromise("./package.json").then(res => console.log(res));
在 node v12 中,引入了 fs Promise api。它們返回 Promise 對(duì)象而不是使用回調(diào)。 API 可通過(guò)require('fs').promises訪問(wèn)。如此一來(lái),開(kāi)發(fā)成本更低了。
const fsPromises = require("fs").promises;
fsPromises
.readFile("./package.json", {
encoding: "utf8",
flag: "r"
})
.then(console.log)
.catch(console.error);
目錄與目錄項(xiàng)
fs.Dir 類:封裝了和文件目錄相關(guān)的操作
fs.Dirent 類:封裝了目錄項(xiàng)的相關(guān)操作。例如判斷設(shè)備類型(字符、塊、FIFO 等)。
它們之間的關(guān)系,通過(guò)代碼展示:
const fsPromises = require("fs").promises;
async function main() {
const dir = await fsPromises.opendir(".");
let dirent = null;
while ((dirent = await dir.read()) !== null) {
console.log(dirent.name);
}
}
main();
文件信息
fs.Stats 類:封裝了文件信息相關(guān)的操作。它在fs.stat()的回調(diào)函數(shù)中返回。
fs.stat("./package.json", (err, stats) => {
if (err) throw err;
console.log(stats);
});
注意,關(guān)于檢查文件是否存在:
- 不建議在調(diào)用 fs.open()、 fs.readFile() 或 fs.writeFile() 之前使用 fs.stat() 檢查文件是否存在。而是應(yīng)該直接打開(kāi)、讀取或?qū)懭胛募?,如果文件不可用則處理引發(fā)的錯(cuò)誤。
- 要檢查文件是否存在但隨后并不對(duì)其進(jìn)行操作,則建議使用 fs.access()
ReadStream 與 WriteStream
在 nodejs 中,stream 是個(gè)非常重要的庫(kù)。很多庫(kù)的 api 都是基于 stream 來(lái)封裝的。例如下面要說(shuō)的 fs 中的 ReadStream 和 WriteStream。
fs 本身提供了 readFile 和 writeFile,它們好用的代價(jià)就是性能有問(wèn)題,會(huì)將內(nèi)容一次全部載入內(nèi)存。但是對(duì)于幾 GB 的大文件,顯然會(huì)有問(wèn)題。
那么針對(duì)大文件的解決方案自然是:一點(diǎn)點(diǎn)讀出來(lái)。這就需要用到 stream 了。以 readStream 為例,代碼如下:
const rs = fs.createReadStream("./package.json");
let content = "";
rs.on("open", () => {
console.log("start to read");
});
rs.on("data", chunk => {
content += chunk.toString("utf8");
});
rs.on("close", () => {
console.log("finish read, content is:\n", content);
});
借助 stream 的 pipe,一行快速封裝一個(gè)大文件的拷貝函數(shù):
function copyBigFile(src, target) {
fs.createReadStream(src).pipe(fs.createWriteStream(target));
}
以上就是如何在Nodejs中使用模塊fs文件系統(tǒng)的詳細(xì)內(nèi)容,更多關(guān)于Nodejs的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
防止Node.js中錯(cuò)誤導(dǎo)致進(jìn)程阻塞的辦法
Node.js我們用到非常的多了,如果我們開(kāi)發(fā)不當(dāng)可能因錯(cuò)誤導(dǎo)致進(jìn)程阻塞問(wèn)題,對(duì)于進(jìn)程阻塞問(wèn)題一直是個(gè)頭痛的事情,今天我們一起來(lái)看一篇關(guān)于Node.js防止錯(cuò)誤導(dǎo)致的進(jìn)程阻塞示例,下面一起來(lái)看看。2016-08-08
Node.js 中正確使用 async/await 與 Promise 
在Node.js中,async/await是ES2017引入的一種更簡(jiǎn)潔的處理異步操作的方式,它基于Promise來(lái)進(jìn)行編寫(xiě),使得異步代碼看起來(lái)更像同步代碼,易于理解和維護(hù),這篇文章主要介紹了Node.js 中正確使用 async/await 與 Promise 對(duì)象配合,需要的朋友可以參考下2024-07-07
NodeJS通過(guò)魔術(shù)封包喚醒局域網(wǎng)計(jì)算機(jī)實(shí)例
這篇文章主要為大家介紹了NodeJS通過(guò)魔術(shù)封包喚醒局域網(wǎng)計(jì)算機(jī)代碼實(shí)例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-06-06
詳解Express筆記之動(dòng)態(tài)渲染HTML(新手入坑)
這篇文章主要介紹了詳解Express筆記之動(dòng)態(tài)渲染HTML(新手入坑),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-12-12
node.js調(diào)用C++函數(shù)的方法示例
這篇文章主要介紹了node.js調(diào)用C++函數(shù)的方法示例,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2018-09-09
Nodejs提取網(wǎng)址參數(shù)解決“querystring”已棄用問(wèn)題
無(wú)論是前端還是后端,經(jīng)常出現(xiàn)的應(yīng)用場(chǎng)景是URL中參數(shù)的處理,下面這篇文章主要給大家介紹了關(guān)于Nodejs提取網(wǎng)址參數(shù)解決“querystring”已棄用問(wèn)題的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-08-08

