fs 模塊
fs 全稱為
file system,稱之為文件系統(tǒng),是 Node.js 中的內(nèi)置模塊,可以對計算機中的磁盤進行操作。
本章節(jié)會介紹如下幾個操作:
- 文件寫入
- 文件讀取
- 文件移動與重命名
- 文件刪除
- 文件夾操作
- 查看資源狀態(tài)
文件寫入
文件寫入就是將數(shù)據(jù)保存到文件中,我們可以使用如下幾個方法來實現(xiàn)該效果
| 方法 | 說明 |
|---|---|
| writeFile | 異步寫入 |
| writeFileSync | 同步寫入 |
| appendFile / appendFileSync | 追加寫入 |
| createWriteStream | 流式寫入 |
writeFile 異步寫入
語法: fs.writeFile(file, data, options, callback)
參數(shù)說明:
file 文件名
data 待寫入的數(shù)據(jù)
options 選項設置
(可選)callback 寫入回調(diào)
返回值: undefined
代碼示例:
// require 是 Node.js 環(huán)境中的 '全局' 變量,用來導入模塊
const fs = require('fs')
// 將 [三人行,必有我?guī)熝伞 寫入到當前文件夾下的 [座右銘.txt] 文件中
fs.writeFile('./座右銘.txt', '三人行,必有我?guī)熝伞?, err =>{
// 如果寫入失敗,則回調(diào)函數(shù)調(diào)用時,會傳入錯誤對象,如寫入成功,會傳入 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 主線程
會等待其線程的執(zhí)行結(jié)果,然后再繼續(xù)執(zhí)行主線程的代碼,效率較低- 異步處理 JavaScript 主線程
不會等待其線程的執(zhí)行結(jié)果,直接執(zhí)行后續(xù)的主線程代碼,效率較好
appendFile / appendFileSync 追加寫入
appendFile作用是在文件尾部追加內(nèi)容,appendFile語法與writeFile語法完全相同
語法:
fs.appendFile(file, data, options, callback)
fs.appendFileSync(file, data, options)
返回值:二者都為 undefined
實例代碼:
fs.append('./座右銘.txt', '則其善者而從之,其不善者而改之。', err =>{
if(err) throw err
console.log('追加成功')
})
fs.appendFileSync('./座右銘.txt','\r\n溫故而知新,可以為師矣')
createWriteStream 流式寫入
語法:fs.createWriteStream(path, options)
參數(shù)說明:
path文件路徑options選項配置(可選)
返回值: Object
代碼示例:
let ws = fs.createWriteStream('./觀書有感.txt')
//寫入數(shù)據(jù)到流
ws.write('半畝方塘一鑒開\r\n')
ws.write('天光云影共徘徊\r\n')
ws.write('問渠那得清如許\r\n')
ws.write('為有源頭活水來\r\n')
//關閉寫入流,表明已沒有數(shù)據(jù)要被寫入可寫流
ws.end()
程序打開一個文件是需要消耗資源的,流式寫入可以減少打開關閉文件的次數(shù)。
流式寫入方式適用于大文件寫入或者頻繁寫入的場景,
writeFile適合于寫入頻率較低的場景
寫入文件的場景
文件寫入 在計算機中是一個非常常見的操作,下面的場景都用到了文件寫入
- 下載文件
- 安裝軟件
- 保存程序日志,如 Git
- 編輯器保存文件
- 視頻錄制
當 需要
持久化保存數(shù)據(jù)的時候,應該想到文件寫入
文件讀取
文件讀取顧名思義,就是通過程序從文件中取出其中的數(shù)據(jù),我們可以使用如下幾種方式:
| 方法 | 說明 |
|---|---|
| readFile | 異步讀取 |
| readFileSync | 同步讀取 |
| createReadStream | 流式讀取 |
readFile 異步讀取
語法: fs.readFile(path, options, callback)
參數(shù)說明:
- path 文件路徑
- options 選項配置
- callback 回調(diào)函數(shù)
返 回 值: undefined
代碼示例:
// 導入 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 選項配置
返 回 值 :string | Buffer
代碼示例:
let data = fs.readFileSync('./座右銘.txt')
let data = fs.readFileSync('./座右銘.txt', 'utf-8')
createReadStream 流式讀取
語法:fs.createReadStream(path, options)
參數(shù)說明:
- path 文件路徑
- options 選項配置(
可選)
返回值:Object
代碼示例:
// 創(chuàng)建讀取流對象
let rs = fs.createReadStream('./觀書有感.txt')
// 每次取出 64k 數(shù)據(jù)后執(zhí)行一次 data 回調(diào)
// 綁定一個 data 事件 chunk 塊兒 大塊兒
re.on('data', chunk =>{
console.log(chunk)
console.log(chunk.length)
})
// 讀取完畢后,執(zhí)行 end 回調(diào) (可選事件)
re.on('end', () =>{
console.log('讀取完畢')
})
讀取文件應用場景
- 電腦開機
- 程序運行
- 編輯器打開文件
- 查看圖片
- 播放視頻
- 播放音樂
- Git 查看日志
- 上傳文件
- 查看聊天記錄
文件移動與重命名
在 Node.js 中,我們可以使用
rename或renameSync來移動或重命名文件或文件夾
語法:
fs.rename(oldPath, newPath, callback)
fs.renameSync(oldPath, newPath)
參數(shù)說明:
- oldPath 文件當前的路徑
- newPath 文件新的路徑
- callback 操作后的回調(diào)
代碼示例:
fs.rename('./觀書有感.txt', './論語/觀書有感.txt', err =>{
if(err) throw err
console.log('移動完成')
})
fs.renameSync('./座右銘.txt', './論語/.我的座右銘.txt')
注: 如果還是移動到當前路徑,但是修改了名字,就是重命名了
文件刪除
在 Node.js 中,我們可以使用
unlink或unlinkSync或rm來刪除文件
語法:
fs.unlink(path, callback)
fs.rm(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 的能力,我們可以對文件夾進行
創(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 選項配置(
可選) - 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 選項配置(
可選) - 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 選項配置( 可選 )
- 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.rmdir('./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來查看資源的詳細信息
語法:
fs.stat(path, options, callback)
fs.statSync(path, options)
參數(shù)說明:
- path 文件夾路徑
- options 選項配置( 可選 )
- 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é)構:
- size 文件體積
- birthtime 創(chuàng)建時間
- mtime 最后修改時間
- isFile 檢測是否為文件
- isDirectory 檢測是否為文件夾
相對路徑問題
fs 模塊對資源進行操作時,路徑的寫法有兩種:
-
相對路徑
-
./座右銘.txt當前目錄下的 座右銘.txt -
座右銘.txt等效于上面的寫法 -
../座右銘.txt當前目錄的上一級目錄中的 座右銘.txt
-
-
絕對路徑
-
D:/Program Fileswindows 系統(tǒng)下的絕對路徑 -
/user/binLinux 系統(tǒng)下的絕對路徑
-
相對路徑中所謂的
當前目錄,指的是命名行的工作目錄,而并非是文件的所在目錄所以當命名行的工作目錄與文件所在目錄不一致時,會出現(xiàn)一些 Bug
__dirname
__dirname 與 require 類似,都是 Node.js 環(huán)境中的 '全局' 變量
__dirname 保存著當前文件夾所在目錄的絕對路徑,可以使用 __dirname 與文件名拼接成絕對路徑
代碼示例:
//=>__dirname + '/data.txt' === 'D:\\Desktop\\Node\\code\\03-fs模塊/data.txt'
let data = fs.readFileSync(__dirname + '/data.txt')
console.log(data)
使用 fs 模塊的時候,盡量使用
__dirname路徑轉(zhuǎn)換為絕對路徑,這樣可以避免相對路徑產(chǎn)生的 Bug
這里的一個左斜杠/相當于倆個右斜杠\\
練習
編寫一個 JS 文件,實現(xiàn)復制文件的功能
/*
* 需求:
* 復制 資料文件夾下的 [笑看風云.mp4]
*/
// 導入 fs 模塊
const fs = require('fs')
// 方式一 readFile
// 讀取文件內(nèi)容
let data = fs.readFileSync('./資料/笑看風云.mp4')
// 寫入文件
fs.writeFileSync('./資料/笑看風云2.mp4', data)
// 方式二 流式操作
// 創(chuàng)建讀取流對象
const rs = fs.createReadStream('./資料/笑看風云.mp4')
// 創(chuàng)建一個寫入流對象
const ws = fs.createWriteStream('./資料/笑看風云3.mp4')
// 綁定data事件
// 理想狀態(tài)下,讀取 64k 就寫入 64 k,這樣消耗的內(nèi)存最少,實際上讀取的速度大于寫入的速度
rs.on('data', chunk => {
ws.write(chunk)
})
// 綁定data事件 ==== rs.pipe(ws)
文件重命名
// 1. 導入 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}`)
})