前言:
????????在Node.js生態系統中,文件系統操作是后端開發不可或缺的一部分。fs模塊作為Node.js核心API的重要組成部分,提供了與文件系統交互的能力,涵蓋了從基礎的文件讀寫到復雜的目錄操作等功能。
????????現代JavaScript開發中,處理本地文件是常見需求,無論是配置文件讀取、日志記錄還是數據持久化存儲。fs模塊通過同步和異步兩種方式提供這些功能,適應不同場景的性能要求。
????????隨著Node.js版本的迭代,fs模塊不斷加入新的特性,如Promise-based API的引入,使得文件操作能夠更好地融入現代異步編程模式。理解并掌握fs模塊,對于構建健壯的Node.js應用具有重要意義。
????????本部分內容將深入解析fs模塊的核心功能,包括常用方法的原理和使用場景,幫助開發者高效安全地處理文件系統操作,為構建復雜應用打下堅實基礎。
1.讀取文件
1.同步
? ? ? ? 使用readFileSync方法,它的寫法簡潔,但會阻塞后面的代碼執行,基本代碼如下:
const fs = require('fs')// 同步寫法 會阻塞后面代碼執行
const read = fs.readFileSync('./a.txt', 'utf8')
console.log(read)
? ? ? ? 在終端中使用 node 文件名 將內容打印出來
????????readFileSync('需要讀取文件的文件名', '編碼')
2.異步
????????使用readFile方法,它接收三個參數,第一個是需要讀取文件的文件名,第二個參數可以接受一個對象,可以在里面設置一些行為,就比如說設置讀取到文字的編碼,第三個參數接受一個回調函數,基本的寫法如下:
const fs = require('fs')// 異步
fs.readFile('./a.txt', {encoding: 'utf8', // 編碼flag: 'r' // 讀取
}, (err, data) => {if (err) throw err // 將錯誤拋出console.log(data)
})
3.promise
? ? ? ? 這種寫法就可以通過.then或.catch來處理成功或失敗的結果,我個人還是推薦使用這種寫法。代碼如下:
const fs = require('fs/promises')// promise
fs.readFile('./a.txt').then(result => {console.log(result.toString('utf8'));
}).catch(err => {throw err
}).finally(()=>{console.log('不管成功與否我都執行');
})
? ? ? ? 看到這可能有些人有點蒙,為什么編碼有這么多種寫法,其實這三種都是可以的,看個人習慣,以及需求。
4.可讀流
? ? ? ? 在處理大文件時會使用到可讀流,它會將文件里的內容一點一點傳過來,假設有一個很大內存的文件,不可能使用readFile一直等著,代碼如下:
const fs = require('fs')// 可讀流 處理大文件
const readStream = fs.createReadStream('./a.txt')readStream.on('data', chunk => {console.log(chunk.toString())
})readStream.on('end', () => {console.log('讀取完成了')
})
2.創建文件夾
? ? ? ? 使用到了mkdirSync,一般都是同步的,因為創建一個文件夾的速度是非常快的。代碼如下:
const fs = require('fs')// 創建文件夾
fs.mkdirSync('./a')
? ? ? ? 如果需要創建一個嵌套的文件夾,會發現比如將路徑改為./a/b/c,這樣是不行的,那如何創建呢,可以使用遞歸,當然不用我們直接寫,只需要添加第二個參數即可,代碼如下:
const fs = require('fs')// 創建嵌套文件夾
fs.mkdirSync('./a/b/c', {recursive: true
})
3.刪除
? ? ? ? 這個比較簡單,使用rm方法,命名跟Linux差不多。代碼如下:
const fs = require('fs')// 刪除
fs.rmSync('./a', {recursive: true
})
? ? ? ? 如果是嵌套的文件夾,只需要遞歸刪除即可。
4.重命名
const fs = require('fs')// 重命名
fs.renameSync('./a.txt', './b.txt')
? ? ? ? 第一個參收是需要重命名文件名稱,第二個參數是要修改的名稱。
5.監聽文件的變化
? ? ? ? 使用watch方法,許多熱更新的底層原來就用到了這個。代碼如下:
const fs = require('fs')// 監聽文件的變化
fs.watch('./a.txt', (event, filename) => {console.log(event, filename);
})
? ? ? ? 當我修改a.txt中的內容時,這個事件就會觸發
6.寫入文件
? ? ? ? 使用writeFile或writeFileSync方法,代碼如下:
const fs = require('fs')// 寫入文件
fs.writeFileSync('./a.txt', '666')
? ? ? ? 當運行腳本會發現,它會將原來文本里面的內容替換成我們寫入的內容,而不是追加,接下來就來說追加的操作。
7.追加寫入文件
1.第一種方法(writeFileSync)
? ? ? ? 寫入的方法也有追加的功能,添加第三個參數,代碼如下:
const fs = require('fs')// 追加文件
fs.writeFileSync('./a.txt', '\n777', {flag: 'a'
})
? ? ? ? a的意思是append追加的意思
2.第二種方法(appendFileSync)
const fs = require('fs')// 追加文件
fs.appendFileSync('./a.txt', '\n888')
8.可寫流
? ? ? ? 從名字可以看出和可讀流類似,可以回顧一下可讀流的意思就可以大致猜到可寫流是什么意思。
? ? ? ? 可寫流的意思就是將大量的數據分批插入。
const fs = require('fs')// 可寫流const writeStream = fs.createWriteStream('./a.txt')const data = ["青山銜落日,","碧水映霞飛。","風過荷香漫,","蟬鳴暮色微。","孤舟橫野渡,","倦鳥宿林扉。","欲寄鄉思遠,","星河入夢歸。"
]data.forEach(item => {writeStream.write(item + '\n')
})// 記得關閉 不然通道一直打開
writeStream.end()// 也可以添加事件 就比如通知寫入完成
writeStream.on('finish',() => {console.log('寫入完成');
})
結語:
????????Node.js的fs模塊為開發者提供了強大而靈活的文件系統操作能力,覆蓋從基礎讀寫到高級流處理的各類場景。通過同步、異步和Promise三種模式,開發者可根據項目需求選擇最佳實踐方式,平衡代碼可讀性與性能要求。
????????文件流處理技術(可讀流/可寫流)尤其適合大文件操作場景,有效避免內存壓力。目錄創建與刪除的遞歸選項、文件監聽機制等特性,為構建自動化工具和實時系統提供了底層支持。
????????現代JavaScript開發中,建議優先考慮Promise-based API或異步模式,結合錯誤處理機制構建健壯的應用。掌握這些核心方法后,開發者可以高效實現配置文件管理、日志系統、數據持久化等關鍵功能,為復雜Node.js應用奠定堅實基礎。