Node 通過封裝基本的POSIX函數(shù)來提供文件系統(tǒng),使用require('fs')來使用這個模塊伙菜,所有與文件相關(guān)的方法轩缤,都提供了異步和同步的形式。 異步的方法通常會將一個可選的回調(diào)函數(shù)作為最后一個參數(shù)贩绕,回調(diào)函數(shù)的第一個參數(shù)通常留給意外情況火的,如果操作是成功的,第一個參數(shù)將是null
或者undeefined
淑倾。 使用同步方法馏鹤,對于任何意外都會即時拋出,可以使用try/catch
語句來處理意外情況娇哆,或者讓錯誤時間向上冒泡湃累。 下面是一個有關(guān)異步方法的基本例子:
const fs = require('fs');
fs.unlink('/tmp/hello', (err) => {
if (err) throw err;
console.log('sucessfully deleted /tmp/hello');
}
再跟著一個同步的例子:
const fs = require('fs');
fs.unlink('/tmp/hello');
console.log('successfully deleted /tmp/hello');
使用異步方法時,需要注意異步方法的執(zhí)行不一定按照書寫順序碍讨,比如下面這種寫法很容易出錯:
fs.rename('/tmp/hello', '/tmp/world', (err) => {
if (err) throw err;
console.log('renamed compelte');
});
fs.stat('/tmp/world', (err, stats) => {if (err) throw err;
console.log(`stats: ${JSON.stringify(stats)}`)});
在這里治力,很可能fs.stat
函數(shù)先于fs.rename
,這樣會出現(xiàn)一些不必要的錯誤勃黍,正確的方法應該是寫在回調(diào)函數(shù)中宵统。
fs.rename('/tmp/hello/', '/tmp/world', (err) ss=> {
if (err) throw err;
fs.stat('/tmp/world'),(err, stats) => {
console.log(`stats: ${JSON.stringfy(stats)});
});
});
執(zhí)行復雜耗時的方法,強烈建議使用異步版本覆获,同步方法在它們執(zhí)行結(jié)束之前马澈,會一直鎖住當前線程,阻斷所有操作弄息。 在fs
模塊中痊班,可以使用相對路徑,但是需要留意參照的路徑來自于process.cwd()的返回值摹量。 很多fs
函數(shù)可以忽略掉回調(diào)參數(shù)涤伐,如果這樣進行使用,默認會拋出錯誤缨称,為了跟蹤到函數(shù)調(diào)用的位置废亭,可以設置NODE_DEBUG
環(huán)境變量:
$ cat script.js
function bad() {
require('fs').readFile('/');ssss
}
bad();
$ env NODE_DEBUG=fs node script.js
fs.js:66
throw err;
^
Error: EISDIR, read
at rethrow (fs.js:61:21)
at maybeCallback (fs.js:79:42)
at Object.fs.readFile (fs.js:153:18)
at bad (/path/to/script.js:2:17)
at Object.<anonymous> (/path/to/script.js:5:1)
<etc.>
fs.watch(filename[, options][, listener]) 監(jiān)聽制定文件或者目錄的變化情況,filename
參數(shù)可以是文件或者目錄具钥,這個方法返回一個fs.FSWather
對象。 第二個參數(shù)是可選的液兽,提供的options
參數(shù)應該是一個對象骂删,里面要求的成員是persistent
和recursive
掌动,這個兩個成員都是布爾類型的值。 用做監(jiān)聽的回調(diào)函數(shù)有兩個參數(shù)宁玫,分別是(event, filename)
粗恢,event
的值視情況,返回字符串change
欧瘪,rename
眷射,文件名指的是觸發(fā)事件的這個文件》鹨矗看下面的這個例子:
// node.md
// 被監(jiān)聽的文件
this is cat.
// app.js
// 用來監(jiān)聽文件改變
fs.watch('./node.md', (event, filename) => {
console.log('下面是event參數(shù)妖碉,event參數(shù)的類型,filename');
console.log(typeof event);
console.log(filename);
});
// node.md
// 這里修改了監(jiān)聽的node.md文件
this is dog.
// console
// 執(zhí)行結(jié)果
下面是event參數(shù)芥被,event參數(shù)的類型欧宜,filename
change
string
node.md
// node.md => node1.md
// 修改文件的名字
// console
// 執(zhí)行結(jié)果
下面是event參數(shù),event參數(shù)的類型拴魄,filename
rename
string
node1.md
注意事項: fs.watch
并不是跨所有平臺的冗茸,在某些常見下不一定可用。 第二個參數(shù)中的布爾值recursive
只在osx和window下可以使用匹中。
可用性:
fs.watch
依賴于操作系統(tǒng)底層模塊夏漱,由操作系統(tǒng)底層模塊通知Node文件的變化。如果某個操作系統(tǒng)底層模塊對于文件的監(jiān)聽本身就有問題顶捷,那么
fs.watch
是無法發(fā)揮作用的挂绰,比如監(jiān)聽了一些不可靠的目錄和文件,網(wǎng)絡文件系統(tǒng)焊切,虛擬機系統(tǒng)中的文件扮授。在linux,osx系統(tǒng)中专肪,
fs.watch
解析路徑成一個索引節(jié)點刹勃,并且監(jiān)聽這個節(jié)點,但是如果監(jiān)聽的節(jié)點被刪除或者重新創(chuàng)建嚎尤,那么此時它就成了一個新節(jié)點了荔仁,watch將會發(fā)送一個delete事件,但是仍然監(jiān)聽原來的節(jié)點芽死,原來的事件不會響應新節(jié)點的改變乏梁,這種處理是符合預期的。-
filename
參數(shù)只支持在linux和windows上面指定(osx也可以关贵,但是有些情況可能會有異常)遇骑,事實上,即便是在可以使用的平臺上揖曾,也不建議直接使用這個參數(shù)落萎,因為在回調(diào)函數(shù)內(nèi)部亥啦,建議增加一些邏輯判斷,看一下filename是否為null练链,如下面的例子:fs.watch('somedir', (event, filename) => { console.log(`event is: ${event}`); if (filename) { console.log(`filename provided: ${filename}`); } else { console.log('filename not provided'); } });