cp无法获取文件状态stat_Node.js从零开始——文件系统
我努力找了找圖,不過清晰度堪憂啊,所以自己做了一張,有點(diǎn)丑不過也就這樣了,哈哈。
今天的內(nèi)容主要就是 Node.js 的文件系統(tǒng),畢竟服務(wù)器么,也有文件服務(wù)器不是?
1 文件系統(tǒng)模塊
這里把文件系統(tǒng)模塊放在前面來說,因?yàn)樯洗蔚?HTTP 模塊相對(duì)簡(jiǎn)單,所以放在了最后,但是有關(guān)文件操作的模塊通常都比較復(fù)雜,為了確保沒接觸過的朋友也能看明白,這次就把它放前面來了。
fs 模塊提供了許多非常實(shí)用的函數(shù)來訪問文件系統(tǒng)并與文件系統(tǒng)進(jìn)行交互,它作為 Node.js 核心的組成部分,無需安裝,可以通過簡(jiǎn)單地引用來使用它:
const一旦這樣做,就可以訪問其所有的方法,包括:
- fs.access():檢查文件是否存在,以及 Node.js 是否有權(quán)限訪問
- fs.appendFile():追加數(shù)據(jù)到文件,如果文件不存在,則創(chuàng)建文件
- fs.chmod(): 更改文件(通過傳入的文件名指定)的權(quán)限,相關(guān)方法:fs.lchmod()、fs.fchmod()
- fs.chown():更改文件(通過傳入的文件名指定)的所有者和群組,相關(guān)方法:fs.fchown()、fs.lchown()
- fs.close():關(guān)閉文件描述符
- fs.copyFile():拷貝文件
- fs.createReadStream():創(chuàng)建可讀的文件流
- fs.createWriteStream():創(chuàng)建可寫的文件流
- fs.link():新建指向文件的硬鏈接
- fs.mkdir():新建文件夾
- fs.mkdtemp():創(chuàng)建臨時(shí)目錄
- fs.open():設(shè)置文件模式
- fs.readdir():讀取目錄的內(nèi)容
- fs.readFile():讀取文件的內(nèi)容,相關(guān)方法:fs.read()
- fs.readlink():讀取符號(hào)鏈接的值
- fs.realpath():將相對(duì)的文件路徑指針(.、..)解析為完整的路徑
- fs.rename():重命名文件或文件夾
- fs.rmdir():刪除文件夾
- fs.stat():返回文件(通過傳入的文件名指定)的狀態(tài),相關(guān)方法:fs.fstat()、fs.lstat()
- fs.symlink():新建文件的符號(hào)鏈接
- fs.truncate():將傳遞的文件名標(biāo)識(shí)的文件截?cái)酁橹付ǖ拈L(zhǎng)度,相關(guān)方法:fs.ftruncate()
- fs.unlink():刪除文件或符號(hào)鏈接
- fs.unwatchFile():停止監(jiān)視文件上的更改
- fs.utimes():更改文件(通過傳入的文件名指定)的時(shí)間戳,相關(guān)方法:fs.futimes()
- fs.watchFile():開始監(jiān)視文件上的更改,相關(guān)方法:fs.watch()
- fs.writeFile():將數(shù)據(jù)寫入文件,相關(guān)方法:fs.write()
關(guān)于 fs 模塊的特殊之處是,所有的方法默認(rèn)情況下都是異步的,但是通過加上 Sync 后綴也可以同步地工作。
例如:
- fs.rename()
- fs.renameSync()
- fs.write()
- fs.writeSync()
這在應(yīng)用程序流程中會(huì)產(chǎn)生巨大的差異。
從 Node.js 10 后,fs 也包括了對(duì) Promise API 的支持,可以參考 FS Promise API。例如,試驗(yàn)一下 fs.rename() 方法, 異步的 API 會(huì)與回調(diào)一起使用:
const同步的 API 則可以這樣使用,并使用 try/catch 塊來處理錯(cuò)誤:
const此處的主要區(qū)別在于,在第二個(gè)示例中,腳本的執(zhí)行會(huì)阻塞(!!很重要,有的時(shí)候反而是解決一些問題的思路),直到文件操作成功。
2 在 Node.js 中使用文件描述符
在與位于文件系統(tǒng)中的文件進(jìn)行交互之前,需要先獲取文件的描述符。
文件描述符是使用 fs 模塊提供的 open() 方法打開文件后返回的:
const注意,將 r 作為 fs.open() 調(diào)用的第二個(gè)參數(shù),意味著打開文件用于讀取。
當(dāng)然如果僅僅是把文件描述符單獨(dú)打印出來,其實(shí)就是個(gè)沒什么意義的字符,比如:
其他常用的標(biāo)志有:
- r+ 打開文件用于讀寫
- w+ 打開文件用于讀寫,將流定位到文件的開頭;如果文件不存在則創(chuàng)建文件
- a 打開文件用于寫入,將流定位到文件的末尾;如果文件不存在則創(chuàng)建文件
- a+ 打開文件用于讀寫,將流定位到文件的末尾;如果文件不存在則創(chuàng)建文件
也可以使用 fs.openSync 方法打開文件,該方法會(huì)返回文件描述符(而不是在回調(diào)中提供):
const一旦獲得文件描述符,就可以以任何方式執(zhí)行所有需要它的操作,例如調(diào)用 fs.open() 以及許多與文件系統(tǒng)交互的其他操作。
3 文件屬性
每個(gè)文件都帶有一組詳細(xì)信息,可以使用 Node.js 進(jìn)行檢查,具體地說,使用 fs 模塊提供的 stat() 方法。
調(diào)用時(shí)傳入文件的路徑,一旦 Node.js 獲得文件的詳細(xì)信息,則會(huì)調(diào)用傳入的回調(diào)函數(shù),并帶上兩個(gè)參數(shù):錯(cuò)誤消息和文件屬性:
constNode.js 也提供了同步的方法,該方法會(huì)阻塞線程,直到文件屬性準(zhǔn)備就緒為止:
const文件的信息包含在屬性變量中,可以通過屬性提取很多信息,包括:
- 使用 stats.isFile() 和 stats.isDirectory() 判斷文件是否目錄或文件
- 使用 stats.isSymbolicLink() 判斷文件是否符號(hào)鏈接
- 使用 stats.size 獲取文件的大小(以字節(jié)為單位)
還有其他一些高級(jí)的方法,但是在日常編程中會(huì)使用的大部分是這些:
const當(dāng)然這里為了能夠輸出結(jié)果,我直接打印在了控制臺(tái),可以直接看到結(jié)果。
4 文件路徑
系統(tǒng)中的每個(gè)文件都有路徑。
在 Linux 和 macOS 上,路徑可能類似于:
/users/joe/file.txt在 Windows 上則有所不同,具有類似以下的結(jié)構(gòu):
C:usersjoefile.txt當(dāng)在應(yīng)用程序中使用路徑時(shí)需要注意,因?yàn)楸仨毧紤]到這種差異;不過好在 PowerShell 的出現(xiàn)使得統(tǒng)一使用類 Unix 路徑成為可能,不過這個(gè)特指相對(duì)路徑,如果是絕對(duì)路徑,那么 Windows 還是必須遵從 [盤符]:[路徑] 的方式。
可以使用以下方式將此模塊引入到文件中:
const現(xiàn)在可以開始使用其方法了。
4.1 從路徑中獲取信息
給定一個(gè)路徑,可以使用以下方法從其中提取信息:
- dirname:獲取文件的父文件夾
- basename:獲取文件名部分
- extname:獲取文件的擴(kuò)展名
例如:
可以通過為 basename 指定第二個(gè)參數(shù)來獲取不帶擴(kuò)展名的文件名:
4.2 使用路徑
可以使用 path.join() 連接路徑的兩個(gè)或多個(gè)片段:
因?yàn)槲矣玫氖?Windows 系統(tǒng),所以 / 或自動(dòng)轉(zhuǎn)換為 ;如果是類 Unix 系統(tǒng),就是正常的 /可以使用 path.resolve() 獲得相對(duì)路徑的絕對(duì)路徑計(jì)算:
同上例在此示例中,Node.js 只是簡(jiǎn)單地將 /server.js 附加到當(dāng)前工作目錄,如果指定第二個(gè)文件夾參數(shù),則 resolve 會(huì)使用第一個(gè)作為第二個(gè)的基礎(chǔ):
如果第一個(gè)參數(shù)以斜杠開頭,則表示它是絕對(duì)路徑:
path.normalize() 是另一個(gè)有用的函數(shù),當(dāng)包含諸如 .、.. 或雙斜杠之類的相對(duì)說明符時(shí),其會(huì)嘗試計(jì)算實(shí)際的路徑:
解析和規(guī)范化都不會(huì)檢查路徑是否存在。 其只是根據(jù)獲得的信息來計(jì)算路徑。
5 讀取文件
在 Node.js 中讀取文件最簡(jiǎn)單的方式是使用 fs.readFile() 方法,向其傳入文件路徑、編碼、以及會(huì)帶上文件數(shù)據(jù)(以及錯(cuò)誤)進(jìn)行調(diào)用的回調(diào)函數(shù):
另外,也可以使用同步的版本 fs.readFileSync():
constfs.readFile() 和 fs.readFileSync() 都會(huì)在返回?cái)?shù)據(jù)之前將文件的全部?jī)?nèi)容讀取到內(nèi)存中。
這意味著大文件會(huì)對(duì)內(nèi)存的消耗和程序執(zhí)行的速度產(chǎn)生重大的影響。
在這種情況下,更好的選擇是使用流來讀取文件的內(nèi)容。
6 寫入文件
在 Node.js 中寫入文件最簡(jiǎn)單的方式是使用 fs.writeFile() API。
例如:
另外,也可以使用同步的版本 fs.writeFileSync():
const默認(rèn)情況下,此 API 會(huì)替換文件的內(nèi)容(如果文件已經(jīng)存在)。
可以通過指定標(biāo)志來修改默認(rèn)的行為:
fs可能會(huì)使用的標(biāo)志有:
- r+ 打開文件用于讀寫
- w+ 打開文件用于讀寫,將流定位到文件的開頭;如果文件不存在則創(chuàng)建文件
- a 打開文件用于寫入,將流定位到文件的末尾;如果文件不存在則創(chuàng)建文件
- a+ 打開文件用于讀寫,將流定位到文件的末尾;如果文件不存在則創(chuàng)建文件
(可以在 http://nodejs.cn/api/fs.html#fs_file_system_flags 中查看更多標(biāo)志)
6.1 追加到文件
將內(nèi)容追加到文件末尾的便捷方法是 fs.appendFile()(及其對(duì)應(yīng)的 fs.appendFileSync()):
6.2 使用流
所有這些方法都是在將全部?jī)?nèi)容寫入文件之后才會(huì)將控制權(quán)返回給程序(在異步的版本中,這意味著執(zhí)行回調(diào))。
在這種情況下,更好的選擇是使用流寫入文件的內(nèi)容。
7 處理文件夾
Node.js 的 fs 核心模塊提供了許多便捷的方法用于處理文件夾。
7.1 檢查文件夾是否存在
使用 fs.access() 檢查文件夾是否存在以及 Node.js 是否具有訪問權(quán)限。
7.2 創(chuàng)建新的文件夾
使用 fs.mkdir() 或 fs.mkdirSync() 可以創(chuàng)建新的文件夾:
7.3 讀取目錄的內(nèi)容
使用 fs.readdir() 或 fs.readdirSync() 可以讀取目錄的內(nèi)容。
這段代碼會(huì)讀取文件夾的內(nèi)容(全部的文件和子文件夾),并返回它們的相對(duì)路徑,因?yàn)橥椒绞奖容^簡(jiǎn)單,不需要太多代碼,所以這個(gè)例子是同步的:
可以獲取完整的路徑:
當(dāng)然在 Windows 上面又變成了這樣,我忍也可以過濾結(jié)果以僅返回文件(排除文件夾):
7.4 重命名文件夾
使用 fs.rename() 或 fs.renameSync() 可以重命名文件或者文件夾,第一個(gè)參數(shù)是當(dāng)前的路徑,第二個(gè)參數(shù)是新的路徑:
文件重命名文件夾重命名fs.renameSync() 是同步的版本:
const7.5 刪除文件夾
使用 fs.rmdir() 或 fs.rmdirSync() 可以刪除文件夾。
刪除包含內(nèi)容的文件夾可能會(huì)更復(fù)雜,因?yàn)檫@個(gè)功能不能同時(shí)刪除文件,所以必須先刪除文件夾內(nèi)的所有文件,才能實(shí)現(xiàn)刪除文件夾的操作。
在這種情況下,最好安裝 fs-extra 模塊,該模塊非常受歡迎且維護(hù)良好,它是 fs 模塊的直接替代品,在其之上提供了更多的功能。
在此示例中,需要的是 remove() 方法。
首先使用以下命令安裝該模塊:
npm install -g fs-extra并像這樣使用它:
也可以與 promise 一起使用:
fs或使用 async/await:
async8 路徑模塊
因?yàn)榍懊嬗玫搅寺窂侥K,所以也簡(jiǎn)單的介紹一下這個(gè)模塊。
path 模塊提供了許多非常實(shí)用的函數(shù)來訪問文件系統(tǒng)并與文件系統(tǒng)進(jìn)行交互,同樣作為 Node.js 核心的組成部分,也是無需安裝的,可以通過簡(jiǎn)單地引用來使用它:
const該模塊提供了 path.sep(作為路徑段分隔符,在 Windows 上是 ,在 Linux/macOS 上是 /)和 path.delimiter(作為路徑定界符,在 Windows 上是 ;,在 Linux/macOS 上是 :)。
還有一下這些 path 方法:
8.1 path.basename()
返回路徑的最后一部分。 第二個(gè)參數(shù)可以過濾掉文件的擴(kuò)展名:
8.2 path.dirname()
返回路徑的目錄部分:
8.3 path.extname()
返回路徑的擴(kuò)展名部分:
8.4 path.isAbsolute()
如果是絕對(duì)路徑,則返回 true:
8.5 path.join()
連接路徑的兩個(gè)或多個(gè)部分:
8.6 path.normalize()
當(dāng)包含類似 .、.. 或雙斜杠等相對(duì)的說明符時(shí),則嘗試計(jì)算實(shí)際的路徑:
8.7 path.parse()
解析對(duì)象的路徑為組成其的片段:
- root:根路徑
- dir:從根路徑開始的文件夾路徑
- base:文件名 + 擴(kuò)展名
- name:文件名
- ext:文件擴(kuò)展名
例如:
require結(jié)果是:
8.8 path.relative()
接受 2 個(gè)路徑作為參數(shù);基于當(dāng)前工作目錄,返回從第一個(gè)路徑到第二個(gè)路徑的相對(duì)路徑。
例如:
8.9 path.resolve()
可以使用 path.resolve() 獲得相對(duì)路徑的絕對(duì)路徑計(jì)算:
通過指定第二個(gè)參數(shù),resolve 會(huì)使用第一個(gè)參數(shù)作為第二個(gè)參數(shù)的基準(zhǔn):
如果第一個(gè)參數(shù)以斜杠開頭,則表示它是絕對(duì)路徑:
當(dāng)然 Windows 是無法省略掉盤符的,所以……不像類 Unix 系統(tǒng)是直接到了根路徑。
總結(jié)
以上是生活随笔為你收集整理的cp无法获取文件状态stat_Node.js从零开始——文件系统的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 什么是云仓
- 下一篇: nextcloud网站不安全_教你搭建私