文件 I/O 是由標準 POSIX 函數(shù)的簡單包裝提供的。通過require('fs')來使用這個模塊。所有的方法都有異步和同步兩種形式。
異步形式的方法通常在最后一個參數(shù)上接受一個回調(diào)函數(shù)?;卣{(diào)函數(shù)的參數(shù)則取決于不同的方法,但是第一個參數(shù)總是為異常所保留。如果操作正常結束,那么第一個參數(shù)會是null或undefined。
當同步形式的方法產(chǎn)生異常時,會立刻拋出。你可以使用try/catch捕獲,或讓它們冒泡。
下面是一個異步方法的例子:
var fs = require('fs');
fs.unlink('/tmp/hello', function (err) {
if (err) throw err;
console.log('successfully deleted /tmp/hello');
});
下面是一個同步方法的例子:
var fs = require('fs');
fs.unlinkSync('/tmp/hello');
console.log('successfully deleted /tmp/hello');
因為異步方法不能夠保證執(zhí)行順序,所以下面的例子很容易出錯:
fs.rename('/tmp/hello', '/tmp/world', function (err) {
if (err) throw err;
console.log('renamed complete');
});
fs.stat('/tmp/world', function (err, stats) {
if (err) throw err;
console.log('stats: ' + JSON.stringify(stats));
});
它需要在fs.rename后執(zhí)行fs.stat。正確的執(zhí)行方法應如下:
fs.rename('/tmp/hello', '/tmp/world', function (err) {
if (err) throw err;
fs.stat('/tmp/world', function (err, stats) {
if (err) throw err;
console.log('stats: ' + JSON.stringify(stats));
});
});
在繁忙的進程中,十分推薦使用異步版本的方法。同步版本的方法會阻塞進程,直到它們完成,也就是說它們會暫停所有連接。
文件的相對路徑也可以被使用,記住路徑是相對于process.cwd()的。
大多數(shù)的fs函數(shù)允許你省略回調(diào)函數(shù)。如果你省略了,將會由一個默認的回調(diào)函數(shù)來重拋出(rethrows)錯誤。要獲得原始調(diào)用地點的堆棧追蹤信息,請設置NODE_DEBUG環(huán)境變量:
$ cat script.js
function bad() {
require('fs').readFile('/');
}
bad();
$ env NODE_DEBUG=fs iojs 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.>
異步版本的rename(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的rename(2)。返回undefined。
異步版本的ftruncate(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的ftruncate(2)。返回undefined。
異步版本的truncate(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。第一個參數(shù)也可以接受一個文件描述符,這樣的話,fs.ftruncate()會被調(diào)用。
同步版本的truncate(2)。返回undefined。
異步版本的chown(2)。回調(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的chown(2)。返回undefined。
異步版本的fchown(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的fchown(2)。返回undefined。
異步版本的lchown(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的lchown(2)。返回undefined。
異步版本的chmod(2)。回調(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的chmod(2)。返回undefined。
異步版本的fchmod(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的fchmod(2)。返回undefined。
異步版本的lchmod(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。
僅在 Mac OS X 中可用。
同步版本的lchmod(2)。返回undefined。
異步版本的stat(2)?;卣{(diào)函數(shù)有兩個參數(shù)(err, stats),stats是一個fs.Stats對象。更多信息請參閱fs.Stats章節(jié)。
異步版本的lstat(2)。回調(diào)函數(shù)有兩個參數(shù)(err, stats),stats是一個fs.Stats對象。lstat()與stat()是相同的,除了path是一個符號鏈接,連接自己本身就是stat-ed,而不是引用一個文件。
異步版本的fstat(2)?;卣{(diào)函數(shù)有兩個參數(shù)(err, stats),stats是一個fs.Stats對象。fstat()與stat()是相同的,除了將要被stat-ed的文件是通過文件描述符fd來指定的。
同步版本的stat(2)。返回一個fs.Stats實例。
同步版本的lstat(2)。返回一個fs.Stats實例。
同步版本的fstat(2)。返回一個fs.Stats實例。
異步版本的link(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的link(2)。返回undefined。
異步版本的symlink(2)。回調(diào)函數(shù)只有一個可能的異常參數(shù)。type參數(shù)可以被設置為'dir','file'或'junction'(默認為'file'),并且僅在 Windows 平臺下可用(其他平臺下會被忽略)。注意Windows junction點 要求目標路徑必須是絕對的。當使用'junction'時,destination參數(shù)會被自動轉(zhuǎn)換為絕對路徑。
同步版本的symlink(2)。返回undefined。
異步版本的link(2)?;卣{(diào)函數(shù)有兩個參數(shù)(err, linkString)。
異步版本的readlink(2),返回一個符號鏈接字符串值。
異步版本的realpath(2)。回調(diào)函數(shù)有兩個參數(shù)(err, resolvedPath)??赡軙褂?code>process.cwd來解析相對路徑。cache是一個包含了路徑映射的對象,被用來 強制進行指定的路徑解析 或 避免對真實路徑調(diào)用額外的fs.stat。
例子:
var cache = {'/etc':'/private/etc'};
fs.realpath('/etc/passwd', cache, function (err, resolvedPath) {
if (err) throw err;
console.log(resolvedPath);
});
同步版本的realpath(2),返回一個解析出的路徑。
異步版本的unlink(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的unlink(2)。返回undefined。
異步版本的rmdir(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的rmdir(2)。返回undefined。
異步版本的mkdir(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。mode默認為0o777。
同步版本的mkdir(2)。返回undefined。
異步版本的readdir(3)。讀取目錄內(nèi)容?;卣{(diào)函數(shù)有兩個參數(shù)(err, files),files是一個目錄中的文件名數(shù)組(不包括'.'和'..')。
同步版本的readdir(3)。返回一個文件名數(shù)組(不包括'.'和'..')。
異步版本的close(2)?;卣{(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的close(2)。返回undefined。
異步版本的文件打開。參閱open(2)。flag可以是:
'r' - 以只讀的方式打開文件。如果文件不存在則拋出異常。
'r+' - 以讀寫的方式打開文件。如果文件不存在則拋出異常。
該功能主要用于打開 NFS 掛載的文件,因為它允許你跳過潛在的過時的本地緩存。它對 I/O 性能有非常大的影響,所以除非需要它,否則不應使用這個flag。
注意這個flag不會將fs.open()變?yōu)橐粋€同步調(diào)用。因為如果你想要同步調(diào)用,你應使用fs.openSync()。
'rs+' - 以讀寫的方式打開文件,告訴操作系統(tǒng)同步地打開它。注意事項請參閱'rs'。
'w' - 以只寫的方式打開文件。如果文件不存在,將會創(chuàng)建它。如果已存在,將會覆蓋它。
'wx' - 類似于'w',但是路徑不存在時會失敗。
'w+' - 以讀寫的方式打開文件。如果文件不存在,將會創(chuàng)建它。如果已存在,將會覆蓋它。
'wx+' - 類似于'w+',但是路徑不存在時會失敗。
'a' - 以附加的形式打開文件。如果文件不存在,將會創(chuàng)建它。
'ax' - 類似于'a',但是路徑不存在時會失敗。
'a+' - 以讀取和附加的形式打開文件。如果文件不存在,將會創(chuàng)建它。
'a+',但是路徑不存在時會失敗。參數(shù)mode用于設置文件模式(權限和sticky bits),但是前提是文件已被創(chuàng)建。它默認為0666,有可讀和可寫權限。
回調(diào)函數(shù)有兩個參數(shù)(err, fd)。
排除標識'x'(open(2)中的O_EXCL標識)保證了目錄是被新創(chuàng)建的。在 POSIX 系統(tǒng)上,即使路徑指向了一個不存在的符號鏈接,也會被認定為文件存在。排除標識不能保證在網(wǎng)絡文件系統(tǒng)中有效。
在 Linux 下,無法對以追加形式打開的文件,在指定位置寫入數(shù)據(jù)。內(nèi)核忽略了位置參數(shù)并且總是將數(shù)據(jù)追加到文件的末尾。
同步版本的fs.open(),返回代表文件描述符的一個整數(shù)。
更改path所指向的文件的時間戳。
同步版本的fs.utimes()。返回undefined。
更改文件描述符fd所指向的文件的時間戳。
同步版本的fs.futimes()。返回undefined。
異步版本的fsync(2)。回調(diào)函數(shù)只有一個可能的異常參數(shù)。
同步版本的fsync(2)。返回undefined。
向文件描述符fd指向的文件寫入buffer。
offset和length決定了buffer的哪一部分被寫入文件。
position指定了文件中,數(shù)據(jù)被寫入的開始位置的偏移量。如果typeof position !== 'number',那么數(shù)據(jù)將會在當前位置被寫入。參閱pwrite(2)。
回調(diào)函數(shù)有三個參數(shù)(err, written, buffer)。written指出了buffer中有多少字節(jié)被寫入。
注意,不等待回調(diào)函數(shù)而多次執(zhí)行fs.write是不安全的。這種情況下推薦使用fs.createWriteStream。
在 Linux 下,無法對以追加形式打開的文件,在指定位置寫入數(shù)據(jù)。內(nèi)核忽略了位置參數(shù)并且總是將數(shù)據(jù)追加到文件的末尾。
向文件描述符fd指向的文件寫入data。如果data不是一個Buffer實例,那么其值將被強制轉(zhuǎn)化為一個字符串。
position指定了文件中,數(shù)據(jù)被寫入的開始位置的偏移量。如果typeof position !== 'number',那么數(shù)據(jù)將會在當前位置被寫入。參閱pwrite(2)。
encoding是期望的字符串編碼。
回調(diào)函數(shù)有三個參數(shù)(err, written, buffer)。written指出了buffer中有多少字節(jié)被寫入。注意,寫入的字節(jié)與字符串字符是不同的。參閱Buffer.byteLength。
與寫入buffer不同,整個字符串都必須被寫入。不能指定子字符串。因為字節(jié)的偏移量可能與字符串的偏移量不相同。
注意,不等待回調(diào)函數(shù)而多次執(zhí)行fs.write是不安全的。這種情況下推薦使用fs.createWriteStream。
在 Linux 下,無法對以追加形式打開的文件,在指定位置寫入數(shù)據(jù)。內(nèi)核忽略了位置參數(shù)并且總是將數(shù)據(jù)追加到文件的末尾。
同步版本的fs.write()。返回被寫入的字節(jié)數(shù)。
從文件描述符fd指向的文件讀取數(shù)據(jù)。
buffer是數(shù)據(jù)將要被寫入的緩沖區(qū)。
offset是開始向buffer寫入數(shù)據(jù)的緩沖區(qū)偏移量。
length是一個指定了讀取字節(jié)數(shù)的整數(shù)。
position是一個指定了從文件的何處開始讀取數(shù)據(jù)的整數(shù)。如果position是null,數(shù)據(jù)將會從當前位置開始讀取。
回調(diào)函數(shù)有三個參數(shù)(err, bytesRead, buffer)。
同步版本的fs.read。返回讀取字節(jié)的個數(shù)。
null'r'異步得讀取文件的所有內(nèi)容。例子:
fs.readFile('/etc/passwd', function (err, data) {
if (err) throw err;
console.log(data);
});
回調(diào)函數(shù)有兩個參數(shù)(err, data),data是文件的內(nèi)容。
如果沒有指定編碼,那么將會返回源buffer。
如果options是一個字符串,那么它將指定編碼,例子:
fs.readFile('/etc/passwd', 'utf8', callback);
同步版本的fs.readFile。返回文件的內(nèi)容。
如果指定了編碼那么將會返回字符串。否則返回buffer。
'utf8'0o666'w'異步地向文件寫入數(shù)據(jù),如果文件已經(jīng)存在,那么會覆蓋它。data可以是一個字符串或一個buffer。
如果數(shù)據(jù)時一個buffer那么編碼會被忽略。編碼默認為'utf8'。
例子:
fs.writeFile('message.txt', 'Hello io.js', function (err) {
if (err) throw err;
console.log('It\'s saved!');
});
如果options是一個字符串,那么它將指定編碼,例子:
fs.writeFile('message.txt', 'Hello io.js', 'utf8', callback);
同步版本的fs.writeFile。返回undefined。
'utf8'0o666'a'異步地向文件追加數(shù)據(jù),如果文件不存在將會創(chuàng)建它。data可以是一個字符串或一個buffer。
例子:
fs.appendFile('message.txt', 'data to append', function (err) {
if (err) throw err;
console.log('The "data to append" was appended to file!');
});
如果options是一個字符串,那么它將指定編碼,例子:
fs.appendFile('message.txt', 'data to append', 'utf8', callback);
同步版本的fs.appendFile。返回undefined。
監(jiān)視文件變化?;卣{(diào)函數(shù)listener會在文件每一次被訪問時調(diào)用。
第二參數(shù)是可選的。如果options被提供,那么它必須是一個含有兩個成員persistent和interval的對象。persistent表明了進程是否在文件被監(jiān)視時繼續(xù)執(zhí)行。interval表明了文件被輪詢的間隔(毫秒)。默認是{ persistent: true, interval: 5007 }。
listener有兩個參數(shù),當前狀態(tài)對象和先前狀態(tài)對象:
fs.watchFile('message.text', function (curr, prev) {
console.log('the current mtime is: ' + curr.mtime);
console.log('the previous mtime was: ' + prev.mtime);
});
這兩個狀態(tài)對象都是fs.Stat實例。
如果你想要在文件被修改時被通知,而不僅僅是在被訪問時,你需要比較curr.mtime和prev.mtime。
注意:fs.watch比fs.watchFile和fs.unwatchFile更高效。當可能時,請使用fs.watch替代它們。
停止監(jiān)視filename的變化。如果指定了listener,那么僅僅會移除指定的listener。否則所有的監(jiān)聽器都會被移除,并且停止繼續(xù)監(jiān)視文件。
對一個沒有被監(jiān)視的文件調(diào)用fs.unwatchFile()將不會發(fā)生任何事,而不是報錯。
注意:fs.watch比fs.watchFile和fs.unwatchFile更高效。當可能時,請使用fs.watch替代它們。
監(jiān)視filename的變化,filename指向的可以是文件也可以是目錄。返回一個fs.FSWatcher對象。
第二個參數(shù)是可選的。options必須是一個對象。支持的布爾值屬性是persistent和recursive。persistent表明了進程是否在文件被監(jiān)視時繼續(xù)執(zhí)行。recursive表明了是否子目錄也需要被監(jiān)視,或僅僅監(jiān)視當前目錄。這只在支持的平臺(參閱下方警告)下傳遞一個目錄時有效。
默認是{ persistent: true, recursive: false }。
listener回調(diào)函數(shù)有兩個參數(shù)(event, filename)。event是'rename'或'change',filename是觸發(fā)事件的文件名。
fs.watch API 不是在所有平臺下都表現(xiàn)一致的,并且在一些情況下是不可用的。
recursive選項目前只支持 OS X。只有FSEvents支持這種類型的文件監(jiān)控,所有其他平臺并不會很快都被支持。
這個特性依賴于底層操作系統(tǒng)提供的文件變化提示。
inotify。kqueue。kqueue,對于目錄它使用FSEvents。Solaris和SmartOS)下,它使用事件端口(event ports)。ReadDirectoryChangesW。如果由于一些原因,底層功能不可用,那么fs.watch的功能也將不可用。例如,在網(wǎng)絡文件系統(tǒng)(NFS,SMB 等)中監(jiān)視文件或目錄變化,往往結果不可靠或完全不可用。
你仍可以使用fs.watchFile,它使用了狀態(tài)輪詢。但是性能更差且可靠性更低。
回調(diào)函數(shù)中提供的filename參數(shù)不是在所有平臺上都支持的(目前只支持 Linux 和 Windows)。即使是在支持的平臺上,filename也不是總會被提供。因此,不要假設filename參數(shù)總會在回調(diào)函數(shù)中被提供,需要有一些檢測它是否為null的邏輯。
fs.watch('somedir', function (event, filename) {
console.log('event is: ' + event);
if (filename) {
console.log('filename provided: ' + filename);
} else {
console.log('filename not provided');
}
});
fs.exists()已被棄用。請使用fs.stat或fs.access替代。
檢查文件系統(tǒng)來測試提供的路徑是否存在。然后在回調(diào)函數(shù)的參數(shù)中提供結果true或false:
fs.exists('/etc/passwd', function (exists) {
util.debug(exists ? "it's there" : "no passwd!");
});
fs.exists()是一個不符合潮流的函數(shù),并且僅因一些歷史原因所以仍然錯在。在你的代碼中,不應有任何原因要繼續(xù)使用它。
特別的,在打開文件前檢查文件是否存在 是一種反模式。因為競態(tài)條件所以讓你的代碼十分脆弱:其他進程可能fs.exists()和fs.open()之間刪除文件。所以僅僅就去打開一個文件,并且當它不存在時處理錯誤。
同步版本的fs.exists。當文件存在,返回true,否則返回false。
fs.existsSync()已被棄用。請使用fs.statSync或fs.accessSync替代。
對于指定的路徑,檢測用戶的權限。mode是一個可選的整數(shù),指定了要被執(zhí)行的可訪問性檢查。以下是mode的一些可用的常量。可以通過“或”運算符(|)連接兩個或以上的值。
rwx權限信息。這是默認值。fs.F_OK一樣)。最后一個參數(shù)callback,是一個包含了潛在錯誤參數(shù)的回調(diào)函數(shù)。如果任何一個可訪問檢查失敗了,錯誤參數(shù)就會被提供。以下是一個在當前進程中檢查/etc/passwd
可讀性和可寫性的例子。
fs.access('/etc/passwd', fs.R_OK | fs.W_OK, function(err) {
util.debug(err ? 'no access!' : 'can read/write');
});
同步版本的fs.access。如果任何一個可訪問性檢查失敗了,它會拋出異常。否則什么都不做。
由fs.stat(),fs.lstat(),fs.lstat()和它們的同步版本函數(shù)所返回的對象。
fs.lstat()時有效)對于一個普通的文件,util.inspect(stats)可能會返回:
{ dev: 2114,
ino: 48064969,
mode: 33188,
nlink: 1,
uid: 85,
gid: 100,
rdev: 0,
size: 527,
blksize: 4096,
blocks: 8,
atime: Mon, 10 Oct 2011 23:24:11 GMT,
mtime: Mon, 10 Oct 2011 23:24:11 GMT,
ctime: Mon, 10 Oct 2011 23:24:11 GMT,
birthtime: Mon, 10 Oct 2011 23:24:11 GMT }
請注意,atime,mtime,birthtime和ctime都是Date對象實例,并且你可以通過合適的方法來比較它們的值。普遍的使用方式是,調(diào)用getTime()來獲取 unix 時間戳并且這個整數(shù)可以被用來進行任何比較。但是還有一些可以展示模糊信息的方法。更多的詳細信息請參閱MDN JavaScript Reference頁。
stat對象中的各個時間有如下語義:
mknod(2),utimes(2)和read(2)系統(tǒng)調(diào)用改變。mknod(2),utimes(2)和write(2)系統(tǒng)調(diào)用改變。chmod(2),chown(2),link(2),mknod(2),rename(2),unlink(2),utimes(2),read(2)和write(2)系統(tǒng)調(diào)用改變。ctime或是1970-01-01T00:00Z(unix時間戳0)填充。在 Darwin 或其他FreeBSD 系統(tǒng)變體上,如果使用utimes(2)系統(tǒng)調(diào)用設置atime為一個比當前birthtime更早的時間,birthtime也會被這樣填充。在io.js v1.0 和 Node v0.12 前,Windows 系統(tǒng)中ctime持有了birthtime值。但是在 v0.12 里,ctime不再是“創(chuàng)建時間”。在 Unix 系統(tǒng)中,它從來都不是。
返回一個新的可讀流對象(參閱Readable Stream)。
options是一個有以下默認值的對象或字符串:
{ flags: 'r',
encoding: null,
fd: null,
mode: 0o666,
autoClose: true
}
options可以包含start和end值來讀取指定范圍的文件數(shù)據(jù)。start和end這兩個位置本身,也都是被包括的,并且start以0開始。編碼可以是'utf8','ascii'或'base64'。
如果指定了fd,可讀流將會忽略path參數(shù)并且將會使用指定的文件描述符。這意味open事件不再會觸發(fā)。
如果autoClose為false,那么文件描述符將不會被關閉,甚至是有錯誤發(fā)生時。關閉它將是你的責任,并且要確保沒有文件描述符泄漏。如果autoClose為true(默認),那么在發(fā)生錯誤時,或到達文件描述末端時,它會被自動關閉。
從一個100字節(jié)的文件中讀取最后10字節(jié)數(shù)據(jù)的例子:
fs.createReadStream('sample.txt', {start: 90, end: 99});
如果options是一個字符串,那么它表示指定的編碼。
ReadStream是一個可讀流。
當可讀流文件被打開時觸發(fā)。
返回一個新的可寫流對象(參閱Writable Stream)。
options是一個有以下默認值的對象或字符串:
{ flags: 'w',
encoding: null,
fd: null,
mode: 0o666 }
options可以包含一個start選項來允許從指定位置開始寫入數(shù)據(jù)。修改一個文件而不是替換它,需要一個r+標識,而不是默認的w。編碼可以是'utf8','ascii','binary'或'base64'。
與上文的ReadStream類似,如果指定了fd,可寫流會忽略path參數(shù),并且使用指定的文件描述符。這意味open事件不再會觸發(fā)。
如果options是一個字符串,那么它表示指定的編碼。
WriteStream是一個可寫流。
WriteStream使用的文件描述符當可寫流文件被打開時觸發(fā)。
至今為止寫入的字節(jié)數(shù)。不包括仍在寫入隊列中的數(shù)據(jù)。
由fs.watch()返回的對象。
停止在指定的fs.FSWatcher上監(jiān)視文件變化。
當被監(jiān)視的目錄或文件發(fā)生了改變時觸發(fā)。詳情參閱fs.watch。
當錯誤發(fā)生時觸發(fā)。