fs 模塊
fs 全稱為
file system,稱之為文件系統(tǒng),是 Node.js 中的內(nèi)置模塊,可以對計(jì)算機(jī)中的磁盤進(jìn)行操作。
本章節(jié)會(huì)介紹如下幾個(gè)操作:
文件寫入
文件讀取
文件移動(dòng)與重命名
文件刪除
文件夾操作
查看資源狀態(tài)
文件寫入
文件寫入就是將 <span style="color:red">數(shù)據(jù)</span> 保存到 <span style="color:red">文件</span> 中,我們可以使用如下幾個(gè)方法來實(shí)現(xiàn)該效果
| 方法 | 說明 |
|---|---|
| writeFile | 異步寫入 |
| writeFileSync | 同步寫入 |
| appendFile / appendFileSync | 追加寫入 |
| createWriteStream | 流式寫入 |
writeFile 異步寫入
語法: fs.writeFile(file, data[, options], callback)
參數(shù)說明:
file 文件名
data 待寫入的數(shù)據(jù)
options 選項(xiàng)設(shè)置
(可選)callback 寫入回調(diào)
返回值: undefined
代碼示例:
// require 是 Node.js 環(huán)境中的 '全局' 變量,用來導(dǎo)入模塊
const fs = require('fs')
// 將 [三人行,必有我?guī)熝?。] 寫入到當(dāng)前文件夾下的 [座右銘.txt] 文件中
fs.writeFile('./座右銘.txt', '三人行,必有我?guī)熝伞?, err =>{
// 如果寫入失敗,則回調(diào)函數(shù)調(diào)用時(shí),會(huì)傳入錯(cuò)誤對象,如寫入成功,會(huì)傳入 null
if(err){
console.log(err)
return
}
console.log('寫入成功')
})
writeFileSync 同步寫入
語法: fs.writeFileSync(file, data[, options])
參數(shù)與 fs.writeFile 大體一致,只是沒有 callback 參數(shù)
返回值:undefined
代碼示例:
try{
fs.writeFileSync('./座右銘.txt', '三人行,必有我?guī)熝伞?)
}catch(e){
console.log(e)
}
Node.js 中的磁盤操作是由其他
線程完成的,結(jié)果的處理有兩種模式:
- 同步處理 JavaScript 主線程
會(huì)等待其線程的執(zhí)行結(jié)果,然后再繼續(xù)執(zhí)行主線程的代碼,效率較低- 異步處理 JavaScript 主線程
不會(huì)等待其線程的執(zhí)行結(jié)果,直接執(zhí)行后續(xù)的主線程代碼,效率較好
appendFile / appendFileSync 追加寫入
appendFile作用是在文件尾部追加內(nèi)容,appendFile語法與writeFile語法完全相同
語法:
fs.appendFile(file, data[, options], callback)
fs.appendFileSync(file, data[, options])
返回值:二者都為 undefined
實(shí)例代碼:
fs.append('./座右銘.txt', '則其善者而從之,其不善者而改之。', err =>{
if(err) throw err
console.log('追加成功')
})
fs.appendFileSync('./座右銘.txt','\r\n溫故而知新,可以為師矣')
createWriteStream 流式寫入
語法:fs.createWriteStream(path[, options])
參數(shù)說明:
path文件路徑options選項(xiàng)配置(可選)
**返回值: **Object
代碼示例:
let ws = fs.createWriteStream('./觀書有感.txt')
//寫入數(shù)據(jù)到流
ws.write('半畝方塘一鑒開\r\n')
ws.write('天光云影共徘徊\r\n')
ws.write('問渠那得清如許\r\n')
ws.write('為有源頭活水來\r\n')
//關(guān)閉寫入流,表明已沒有數(shù)據(jù)要被寫入可寫流
ws.end()
<span style="color:red">程序打開一個(gè)文件是需要消耗資源的</span>,流式寫入可以減少打開關(guān)閉文件的次數(shù)。
流式寫入方式適用于 <span style="color:red">大文件寫入或者頻繁寫入</span>的場景,
writeFile適合于 <span style="color:red">寫入頻率較低的場景</span>
寫入文件的場景
文件寫入 在計(jì)算機(jī)中是一個(gè)非常常見的操作,下面的場景都用到了文件寫入
下載文件
安裝軟件
保存程序日志,如 Git
編輯器保存文件
視頻錄制
當(dāng) <span style="color:red">需要持久化保存數(shù)據(jù)</span> 的時(shí)候,應(yīng)該想到
文件寫入
文件讀取
文件讀取顧名思義,就是通過程序從文件中取出其中的數(shù)據(jù),我們可以使用如下幾種方式:
| 方法 | 說明 |
|---|---|
| readFile | 異步讀取 |
| readFileSync | 同步讀取 |
| createReadStream | 流式讀取 |
readFile 異步讀取
語法: fs.readFile(path[, options], callback)
參數(shù)說明:
path 文件路徑
options 選項(xiàng)配置
callback 回調(diào)函數(shù)
返 回 值 : undefined
代碼示例:
// 導(dǎo)入 fs 模塊
fs.readFile('./座右銘.txt', (error,data) =>{
if(err) throw err
console.log(data)
})
fs.readFile('./座右銘.txt', 'uft-8', (error,data) =>{
if(err) throw err
console.log(data)
})
readFileSync 同步讀取
語法:fs.readFileSync(path[, options])
參數(shù)說明:
path 文件路徑
options 選項(xiàng)配置
返 回 值 :string | Buffer
代碼示例:
let data = fs.readFileSync('./座右銘.txt')
let data = fs.readFileSync('./座右銘.txt', 'utf-8')
createReadStream 流式讀取
語法:fs.createReadStream(path[, options])
參數(shù)說明:
path 文件路徑
options 選項(xiàng)配置(
可選)
返回值:Object
代碼示例:
// 創(chuàng)建讀取流對象
let rs = fs.createReadStream('./觀書有感.txt')
// 每次取出 64k 數(shù)據(jù)后執(zhí)行一次 data 回調(diào)
// 綁定一個(gè) data 事件 chunk 塊兒 大塊兒
re.on('data', chunk =>{
console.log(chunk)
console.log(chunk.length)
})
// 讀取完畢后,執(zhí)行 end 回調(diào) (可選事件)
re.on('end', () =>{
console.log('讀取完畢')
})
讀取文件應(yīng)用場景
電腦開機(jī)
程序運(yùn)行
編輯器打開文件
查看圖片
播放視頻
播放音樂
Git 查看日志
上傳文件
查看聊天記錄
文件移動(dòng)與重命名
在 Node.js 中,我們可以使用
rename或renameSync來移動(dòng)或重命名文件或文件夾
語法:
fs.rename(oldPath, newPath, callback)
fs.renameSync(oldPath, newPath)
參數(shù)說明:
oldPath 文件當(dāng)前的路徑
newPath 文件新的路徑
callback 操作后的回調(diào)
代碼示例:
fs.rename('./觀書有感.txt', './論語/觀書有感.txt', err =>{
if(err) throw err
console.log('移動(dòng)完成')
})
fs.renameSync('./座右銘.txt', './論語/.我的座右銘.txt')
注: 如果還是移動(dòng)到當(dāng)前路徑,但是修改了名字,就是重命名了
文件刪除
在 Node.js 中,我們可以使用
unlink或unlinkSync來刪除文件
語法:
fs.unlink(path, callback)
fs.unlinkSync(path)
參數(shù)說明:
path 文件路徑
callback 操作后的回調(diào)
代碼示例:
const fs = require('fs')
fs.unlink('./test.txt', err =>{
if(err) throw err
console.log('刪除成功')
})
fs.unlinkSync('./test2.txt')
// 調(diào)用 rm 方法 14.4 同步 rmSync
fs.rm('./論語.txt', err => {
if (err) {
console.log('刪除失敗')
return
}
console.log('刪除成功')
})
文件夾操作
借助 Node.js 的能力,我們可以對文件夾進(jìn)行
創(chuàng)建、讀取、刪除等操作
| 方法 | 說明 |
|---|---|
| mkdir / mkdirSync | 創(chuàng)建文件夾 |
| readdir / readdirSync | 讀取文件夾 |
| rmdir / rmdirSync | 刪除文件夾 |
mkdir 創(chuàng)建文件夾
在 Node.js 中,我們可以使用
mkdir或mkdirSync來創(chuàng)建文件夾
語法:
fs.mkdir(path[, options], callback)
fs.mkdirSync(path[, options])
參數(shù)說明:
path 文件夾路徑
options 選項(xiàng)配置(
可選)callback 操作后的回調(diào)
示例代碼:
// 異步創(chuàng)建文件夾 mk make 制作 dir directory 文件夾
fs.mkdir('./page', err =>{
if(err) throw err
console.log('創(chuàng)建成功')
})
// 遞歸異步創(chuàng)建
fs.mkdir('./1/2/3', {recursive: true}, err =>{
if(err) throw err
console.log('遞歸創(chuàng)建成功')
})
// 遞歸同步創(chuàng)建文件夾
fs.mkdirSync('./x/y/z', {recursive: true})
readdir 讀取文件夾
在 Node.js 中,我們可以使用
readdir或readdirSync來讀取文件夾
語法:
fs.readdir(path[, options], callback)
fs.readdirSync(path[, options])
參數(shù)說明:
path 文件夾路徑
options 選項(xiàng)配置(
可選)callback 操作后的回調(diào)
示例代碼:
// 異步讀取
fs.readdir('./論語', (err, data) => {
if(err) throw err
console.log(data)
})
// 同步讀取
let data = fs.readdirSync('./論語')
console.log(data)
rmdir 刪除文件夾
在 Node.js 中,我們可以使用
rmdir或rmdirSync來刪除文件夾
語法:
fs.rmdir(path[, options], callback)
fs.redirSync(path[, options])
參數(shù)說明:
path 文件夾路徑
options 選項(xiàng)配置( 可選 )
callback 操作后的回調(diào)
示例代碼:
// 異步刪除文件夾 rm remove 移除
fs.rmdir('./page', err => {
if(err) throw err
console.log('刪除成功')
})
//異步遞歸刪除文件夾 不推薦
//=>DeprecationWarning: In future versions of Node.js, fs.rmdir(path, { recursive: true }) will be removed. Use fs.rm(path, { recursive: true }) instead
fs.rmdirSync('./1', {recursive: true}, err => {
if(err){
console.log(err)
return
}
console.log('遞歸刪除')
})
//同步遞歸刪除文件夾
fs.rmdirSync('./x', {recursive: true})
// 建議使用
fs.rm('./a', { recursive: true }, err => {
if (err) {
console.log(err)
return
}
console.log('刪除成功')
})
查看資源狀態(tài)
在 Node.js 中,我們可以使用
stat或statSync來查看資源的詳細(xì)信息
語法:
fs.stat(path[, options], callback)
fs.statSync(path[, options])
參數(shù)說明:
path 文件夾路徑
options 選項(xiàng)配置( 可選 )
callback 操作后的回調(diào)
示例代碼:
// 異步獲取狀態(tài)
// stat 方法 status 縮寫 狀態(tài)
fs.stat('/data.txt', (err, data) =>{
if(err) throw err
console.log(data)
})
// 同步獲取狀態(tài)
let data = fs.statSync('./data.txt')

結(jié)果值對象結(jié)構(gòu):
size 文件體積
birthtime 創(chuàng)建時(shí)間
mtime 最后修改時(shí)間
isFile 檢測是否為文件
isDirectory 檢測是否為文件夾
....
相對路徑問題
fs 模塊對資源進(jìn)行操作時(shí),路徑的寫法有兩種:
-
相對路徑
-
./座右銘.txt當(dāng)前目錄下的 座右銘.txt -
座右銘.txt等效于上面的寫法 -
../座右銘.txt當(dāng)前目錄的上一級目錄中的 座右銘.txt
-
-
絕對路徑
-
D:/Program Fileswindows 系統(tǒng)下的絕對路徑 -
/user/binLinux 系統(tǒng)下的絕對路徑
-
相對路徑中所謂的
當(dāng)前目錄,指的是命名行的工作目錄,而并非是文件的所在目錄所以當(dāng)命名行的工作目錄與文件所在目錄不一致時(shí),會(huì)出現(xiàn)一些 Bug
__dirname
__dirname 與 require 類似,都是 Node.js 環(huán)境中的 '全局' 變量
__dirname 保存著 <span style="color:red">當(dāng)前文件夾所在目錄的絕對路徑</span>,可以使用 __dirname 與文件名拼接成絕對路徑
代碼示例:
//=>__dirname + '/data.txt' === 'D:\\Desktop\\Node\\code\\03-fs模塊/data.txt'
let data = fs.readFileSync(__dirname + '/data.txt')
console.log(data)
使用 fs 模塊的時(shí)候,盡量使用
__dirname路徑轉(zhuǎn)換為絕對路徑,這樣可以避免相對路徑產(chǎn)生的 Bug
練習(xí)
編寫一個(gè) JS 文件,實(shí)現(xiàn)復(fù)制文件的功能
/*
* 需求:
* 復(fù)制 資料文件夾下的 [笑看風(fēng)云.mp4]
*/
// 導(dǎo)入 fs 模塊
const fs = require('fs')
// 方式一 readFile
// 讀取文件內(nèi)容
let data = fs.readFileSync('./資料/笑看風(fēng)云.mp4')
// 寫入文件
fs.writeFileSync('./資料/笑看風(fēng)云2.mp4', data)
// 方式二 流式操作
// 創(chuàng)建讀取流對象
const rs = fs.createReadStream('./資料/笑看風(fēng)云.mp4')
// 創(chuàng)建一個(gè)寫入流對象
const ws = fs.createWriteStream('./資料/笑看風(fēng)云3.mp4')
// 綁定data事件
// 理想狀態(tài)下,讀取 64k 就寫入 64 k,這樣消耗的內(nèi)存最少,實(shí)際上讀取的速度大于寫入的速度
rs.on('data', chunk => {
ws.write(chunk)
})
// 綁定data事件 ==== rs.pipe(ws)
文件重命名
// 1. 導(dǎo)入 fs 模塊
const fs = require('fs')
// 讀取 03-fs模塊 文件夾
const files = fs.readdirSync('../03-fs模塊')
// 遍歷數(shù)組
files.forEach(item => {
// 判斷
let [num, name] = item.split('-')
if (num < 10) {
num = '0' + num
}
// 創(chuàng)建新的文件名
let newName = num + '-' + name
// 重命名
fs.renameSync(`../03-fs模塊/${item}`, `../03-fs模塊/${newName}`)
})