Node.js 檔案系統

Node.js 檔案系統

Node.js 提供一組類似 UNIX(POSIX)標準的檔案操作API。 Node 匯入檔案系統模組(fs)語法如下所示:

var fs = require("fs")

非同步和同步

Node.js 檔案系統(fs 模組)模組中的方法均有非同步和同步版本,例如讀取檔案內容的函式有非同步的 fs.readFile() 和同步的 fs.readFileSync()。

非同步的方法函式最後一個引數為回撥函式,回撥函式的第一個引數包含了錯誤資訊(error)。

建議大家使用非同步方法,比起同步,非同步方法效能更高,速度更快,而且沒有阻塞。

例項

建立 input.txt 檔案,內容如下:

入門教學官網地址:www.itread01.com
檔案讀取例項

建立 file.js 檔案, 程式碼如下:

var fs = require("fs");

// 非同步讀取
fs.readFile('input.txt', function (err, data) {
   if (err) {
       return console.error(err);
   }
   console.log("非同步讀取: " + data.toString());
});

// 同步讀取
var data = https://www.itread01.com/nodejs/fs.readFileSync('input.txt');
console.log("同步讀取: " + data.toString());

console.log("程式執行完畢。");

以上程式碼執行結果如下:

$ node file.js 
同步讀取: 入門教學官網地址:www.itread01.com
檔案讀取例項

程式執行完畢。
非同步讀取: 入門教學官網地址:www.itread01.com
檔案讀取例項

接下來,讓我們來具體瞭解下 Node.js 檔案系統的方法。


開啟檔案

語法

以下為在非同步模式下開啟檔案的語法格式:

fs.open(path, flags[, mode], callback)

引數

引數使用說明如下:

  • path - 檔案的路徑。

  • flags - 檔案開啟的行為。具體值詳見下文。

  • mode - 設定檔案模式(許可權),檔案建立預設許可權為 0666(可讀,可寫)。

  • callback - 回撥函式,帶有兩個引數如:callback(err, fd)。

flags 引數可以是以下值:

Flag描述
r以讀取模式開啟檔案。如果檔案不存在丟擲異常。
r+ 以讀寫模式開啟檔案。如果檔案不存在丟擲異常。
rs以同步的方式讀取檔案。
rs+以同步的方式讀取和寫入檔案。
w以寫入模式開啟檔案,如果檔案不存在則建立。
wx類似 'w',但是如果檔案路徑存在,則檔案寫入失敗。
w+以讀寫模式開啟檔案,如果檔案不存在則建立。
wx+類似 'w+', 但是如果檔案路徑存在,則檔案讀寫失敗。
a以追加模式開啟檔案,如果檔案不存在則建立。
ax類似 'a', 但是如果檔案路徑存在,則檔案追加失敗。
a+以讀取追加模式開啟檔案,如果檔案不存在則建立。
ax+類似 'a+', 但是如果檔案路徑存在,則檔案讀取追加失敗。

例項

接下來我們建立 file.js 檔案,並開啟 input.txt 檔案進行讀寫,程式碼如下所示:

var fs = require("fs");

// 非同步開啟檔案
console.log("準備開啟檔案!");
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
  console.log("檔案開啟成功!");     
});

以上程式碼執行結果如下:

$ node file.js 
準備開啟檔案!
檔案開啟成功!

獲取檔案資訊

語法

以下為通過非同步模式獲取檔案資訊的語法格式:

fs.stat(path, callback)

引數

引數使用說明如下:

  • path - 檔案路徑。

  • callback - 回撥函式,帶有兩個引數如:(err, stats), stats 是 fs.Stats 物件。

fs.stat(path)執行後,會將stats類的例項返回給其回撥函式。可以通過stats類中的提供方法判斷檔案的相關屬性。例如判斷是否為檔案:

var fs = require('fs');

fs.stat('/Users/liuht/code/itbilu/demo/fs.js', function (err, stats) {
    console.log(stats.isFile());         //true
})

stats類中的方法有:

方法描述
stats.isFile()如果是檔案返回 true,否則返回 false。
stats.isDirectory()如果是目錄返回 true,否則返回 false。
stats.isBlockDevice()如果是塊裝置返回 true,否則返回 false。
stats.isCharacterDevice()如果是字元裝置返回 true,否則返回 false。
stats.isSymbolicLink()如果是軟連結返回 true,否則返回 false。
stats.isFIFO()如果是FIFO,返回true,否則返回 false。FIFO是UNIX中的一種特殊型別的命令管道。
stats.isSocket()如果是 Socket 返回 true,否則返回 false。

例項

接下來我們建立 file.js 檔案,程式碼如下所示:

var fs = require("fs");

console.log("準備開啟檔案!");
fs.stat('input.txt', function (err, stats) {
   if (err) {
       return console.error(err);
   }
   console.log(stats);
   console.log("讀取檔案資訊成功!");
   
   // 檢測檔案型別
   console.log("是否為檔案(isFile) ? " + stats.isFile());
   console.log("是否為目錄(isDirectory) ? " + stats.isDirectory());    
});

以上程式碼執行結果如下:

$ node file.js 
準備開啟檔案!
{ dev: 16777220,
  mode: 33188,
  nlink: 1,
  uid: 501,
  gid: 20,
  rdev: 0,
  blksize: 4096,
  ino: 40333161,
  size: 61,
  blocks: 8,
  atime: Mon Sep 07 2015 17:43:55 GMT+0800 (CST),
  mtime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST),
  ctime: Mon Sep 07 2015 17:22:35 GMT+0800 (CST) }
讀取檔案資訊成功!
是否為檔案(isFile) ? true
是否為目錄(isDirectory) ? false

寫入檔案

語法

以下為非同步模式下寫入檔案的語法格式:

fs.writeFile(file, data[, options], callback)

writeFile 直接開啟檔案預設是 w 模式,所以如果檔案存在,該方法寫入的內容會覆蓋舊的檔案內容。

引數

引數使用說明如下:

  • file - 檔名或檔案描述符。

  • data - 要寫入檔案的資料,可以是 String(字串) 或 Buffer(緩衝) 物件。

  • options - 該引數是一個物件,包含 {encoding, mode, flag}。預設編碼為 utf8, 模式為 0666 , flag 為 'w'

  • callback - 回撥函式,回撥函式只包含錯誤資訊引數(err),在寫入失敗時返回。

例項

接下來我們建立 file.js 檔案,程式碼如下所示:

var fs = require("fs");

console.log("準備寫入檔案");
fs.writeFile('input.txt', '我是通 過fs.writeFile 寫入檔案的內容',  function(err) {
   if (err) {
       return console.error(err);
   }
   console.log("資料寫入成功!");
   console.log("--------我是分割線-------------")
   console.log("讀取寫入的資料!");
   fs.readFile('input.txt', function (err, data) {
      if (err) {
         return console.error(err);
      }
      console.log("非同步讀取檔案資料: " + data.toString());
   });
});

以上程式碼執行結果如下:

$ node file.js 
準備寫入檔案
資料寫入成功!
--------我是分割線-------------
讀取寫入的資料!
非同步讀取檔案資料: 我是通 過fs.writeFile 寫入檔案的內容

讀取檔案

語法

以下為非同步模式下讀取檔案的語法格式:

fs.read(fd, buffer, offset, length, position, callback)

該方法使用了檔案描述符來讀取檔案。

引數

引數使用說明如下:

  • fd - 通過 fs.open() 方法返回的檔案描述符。

  • buffer - 資料寫入的緩衝區。

  • offset - 緩衝區寫入的寫入偏移量。

  • length - 要從檔案中讀取的位元組數。

  • position - 檔案讀取的起始位置,如果 position 的值為 null,則會從當前檔案指標的位置讀取。

  • callback - 回撥函式,有三個引數err, bytesRead, buffer,err 為錯誤資訊, bytesRead 表示讀取的位元組數,buffer 為緩衝區物件。

例項

input.txt 檔案內容為:

入門教學官網地址:www.itread01.com

接下來我們建立 file.js 檔案,程式碼如下所示:

var fs = require("fs");
var buf = new Buffer.alloc(1024);

console.log("準備開啟已存在的檔案!");
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
   console.log("檔案開啟成功!");
   console.log("準備讀取檔案:");
   fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
      if (err){
         console.log(err);
      }
      console.log(bytes + "  位元組被讀取");
      
      // 僅輸出讀取的位元組
      if(bytes > 0){
         console.log(buf.slice(0, bytes).toString());
      }
   });
});

以上程式碼執行結果如下:

$ node file.js 
準備開啟已存在的檔案!
檔案開啟成功!
準備讀取檔案:
42  位元組被讀取
入門教學官網地址:www.itread01.com

關閉檔案

語法

以下為非同步模式下關閉檔案的語法格式:

fs.close(fd, callback)

該方法使用了檔案描述符來讀取檔案。

引數

引數使用說明如下:

  • fd - 通過 fs.open() 方法返回的檔案描述符。

  • callback - 回撥函式,沒有引數。

例項

input.txt 檔案內容為:

入門教學官網地址:www.itread01.com

接下來我們建立 file.js 檔案,程式碼如下所示:

var fs = require("fs");
var buf = new Buffer.alloc(1024);

console.log("準備開啟檔案!");
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
   console.log("檔案開啟成功!");
   console.log("準備讀取檔案!");
   fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
      if (err){
         console.log(err);
      }

      // 僅輸出讀取的位元組
      if(bytes > 0){
         console.log(buf.slice(0, bytes).toString());
      }

      // 關閉檔案
      fs.close(fd, function(err){
         if (err){
            console.log(err);
         } 
         console.log("檔案關閉成功");
      });
   });
});

以上程式碼執行結果如下:

$ node file.js 
準備開啟檔案!
檔案開啟成功!
準備讀取檔案!
入門教學官網地址:www.itread01.com
檔案關閉成功

擷取檔案

語法

以下為非同步模式下擷取檔案的語法格式:

fs.ftruncate(fd, len, callback)

該方法使用了檔案描述符來讀取檔案。

引數

引數使用說明如下:

  • fd - 通過 fs.open() 方法返回的檔案描述符。

  • len - 檔案內容擷取的長度。

  • callback - 回撥函式,沒有引數。

例項

input.txt 檔案內容為:

site:www.itread01.com

接下來我們建立 file.js 檔案,程式碼如下所示:

var fs = require("fs");
var buf = new Buffer.alloc(1024);

console.log("準備開啟檔案!");
fs.open('input.txt', 'r+', function(err, fd) {
   if (err) {
       return console.error(err);
   }
   console.log("檔案開啟成功!");
   console.log("擷取10位元組內的檔案內容,超出部分將被去除。");
   
   // 擷取檔案
   fs.ftruncate(fd, 10, function(err){
      if (err){
         console.log(err);
      } 
      console.log("檔案擷取成功。");
      console.log("讀取相同的檔案"); 
      fs.read(fd, buf, 0, buf.length, 0, function(err, bytes){
         if (err){
            console.log(err);
         }

         // 僅輸出讀取的位元組
         if(bytes > 0){
            console.log(buf.slice(0, bytes).toString());
         }

         // 關閉檔案
         fs.close(fd, function(err){
            if (err){
               console.log(err);
            } 
            console.log("檔案關閉成功!");
         });
      });
   });
});

以上程式碼執行結果如下:

$ node file.js 
準備開啟檔案!
檔案開啟成功!
擷取10位元組內的檔案內容,超出部分將被去除。
檔案擷取成功。
讀取相同的檔案
site:www.r
檔案關閉成功

刪除檔案

語法

以下為刪除檔案的語法格式:

fs.unlink(path, callback)

引數

引數使用說明如下:

  • path - 檔案路徑。

  • callback - 回撥函式,沒有引數。

例項

input.txt 檔案內容為:

site:www.itread01.com

接下來我們建立 file.js 檔案,程式碼如下所示:

var fs = require("fs");

console.log("準備刪除檔案!");
fs.unlink('input.txt', function(err) {
   if (err) {
       return console.error(err);
   }
   console.log("檔案刪除成功!");
});

以上程式碼執行結果如下:

$ node file.js 
準備刪除檔案!
檔案刪除成功!

再去檢視 input.txt 檔案,發現已經不存在了。


建立目錄

語法

以下為建立目錄的語法格式:

fs.mkdir(path[, options], callback)

引數

引數使用說明如下:

  • path - 檔案路徑。

  • options 引數可以是:

    • recursive - 是否以遞迴的方式建立目錄,預設為 false。
    • mode - 設定目錄許可權,預設為 0777。
  • callback - 回撥函式,沒有引數。

例項

接下來我們建立 file.js 檔案,程式碼如下所示:

var fs = require("fs");
// tmp 目錄必須存在
console.log("建立目錄 /tmp/test/");
fs.mkdir("/tmp/test/",function(err){
   if (err) {
       return console.error(err);
   }
   console.log("目錄建立成功。");
});

以上程式碼執行結果如下:

$ node file.js 
建立目錄 /tmp/test/
目錄建立成功。

可以新增 recursive: true 引數,不管建立的目錄 /tmp 和 /tmp/a 是否存在:

fs.mkdir('/tmp/a/apple', { recursive: true }, (err) => {
  if (err) throw err;
});

讀取目錄

語法

以下為讀取目錄的語法格式:

fs.readdir(path, callback)

引數

引數使用說明如下:

  • path - 檔案路徑。

  • callback - 回撥函式,回撥函式帶有兩個引數err, files,err 為錯誤資訊,files 為 目錄下的檔案陣列列表。

例項

接下來我們建立 file.js 檔案,程式碼如下所示:

var fs = require("fs");

console.log("檢視 /tmp 目錄");
fs.readdir("/tmp/",function(err, files){
   if (err) {
       return console.error(err);
   }
   files.forEach( function (file){
       console.log( file );
   });
});

以上程式碼執行結果如下:

$ node file.js 
檢視 /tmp 目錄
input.out
output.out
test
test.txt

刪除目錄

語法

以下為刪除目錄的語法格式:

fs.rmdir(path, callback)

引數

引數使用說明如下:

  • path - 檔案路徑。

  • callback - 回撥函式,沒有引數。

例項

接下來我們建立 file.js 檔案,程式碼如下所示:

var fs = require("fs");
// 執行前建立一個空的 /tmp/test 目錄
console.log("準備刪除目錄 /tmp/test");
fs.rmdir("/tmp/test",function(err){
   if (err) {
       return console.error(err);
   }
   console.log("讀取 /tmp 目錄");
   fs.readdir("/tmp/",function(err, files){
      if (err) {
          return console.error(err);
      }
      files.forEach( function (file){
          console.log( file );
      });
   });
});

以上程式碼執行結果如下:

$ node file.js 
準備刪除目錄 /tmp/test
讀取 /tmp 目錄
……

檔案模組方法參考手冊

以下為 Node.js 檔案模組相同的方法列表:

序號方法 & 描述
1fs.rename(oldPath, newPath, callback)
非同步 rename().回撥函式沒有引數,但可能丟擲異常。
2fs.ftruncate(fd, len, callback)
非同步 ftruncate().回撥函式沒有引數,但可能丟擲異常。
3fs.ftruncateSync(fd, len)
同步 ftruncate()
4fs.truncate(path, len, callback)
非同步 truncate().回撥函式沒有引數,但可能丟擲異常。
5fs.truncateSync(path, len)
同步 truncate()
6fs.chown(path, uid, gid, callback)
非同步 chown().回撥函式沒有引數,但可能丟擲異常。
7fs.chownSync(path, uid, gid)
同步 chown()
8fs.fchown(fd, uid, gid, callback)
非同步 fchown().回撥函式沒有引數,但可能丟擲異常。
9fs.fchownSync(fd, uid, gid)
同步 fchown()
10fs.lchown(path, uid, gid, callback)
非同步 lchown().回撥函式沒有引數,但可能丟擲異常。
11fs.lchownSync(path, uid, gid)
同步 lchown()
12fs.chmod(path, mode, callback)
非同步 chmod().回撥函式沒有引數,但可能丟擲異常。
13fs.chmodSync(path, mode)
同步 chmod().
14fs.fchmod(fd, mode, callback)
非同步 fchmod().回撥函式沒有引數,但可能丟擲異常。
15fs.fchmodSync(fd, mode)
同步 fchmod().
16fs.lchmod(path, mode, callback)
非同步 lchmod().回撥函式沒有引數,但可能丟擲異常。Only available on Mac OS X.
17fs.lchmodSync(path, mode)
同步 lchmod().
18fs.stat(path, callback)
非同步 stat(). 回撥函式有兩個引數 err, stats,stats 是 fs.Stats 物件。
19fs.lstat(path, callback)
非同步 lstat(). 回撥函式有兩個引數 err, stats,stats 是 fs.Stats 物件。
20fs.fstat(fd, callback)
非同步 fstat(). 回撥函式有兩個引數 err, stats,stats 是 fs.Stats 物件。
21fs.statSync(path)
同步 stat(). 返回 fs.Stats 的例項。
22fs.lstatSync(path)
同步 lstat(). 返回 fs.Stats 的例項。
23fs.fstatSync(fd)
同步 fstat(). 返回 fs.Stats 的例項。
24fs.link(srcpath, dstpath, callback)
非同步 link().回撥函式沒有引數,但可能丟擲異常。
25fs.linkSync(srcpath, dstpath)
同步 link().
26fs.symlink(srcpath, dstpath[, type], callback)
非同步 symlink().回撥函式沒有引數,但可能丟擲異常。 type 引數可以設定為 'dir', 'file', 或 'junction' (預設為 'file') 。
27fs.symlinkSync(srcpath, dstpath[, type])
同步 symlink().
28fs.readlink(path, callback)
非同步 readlink(). 回撥函式有兩個引數 err, linkString。
29fs.realpath(path[, cache], callback)
非同步 realpath(). 回撥函式有兩個引數 err, resolvedPath。
30fs.realpathSync(path[, cache])
同步 realpath()。返回絕對路徑。
31fs.unlink(path, callback)
非同步 unlink().回撥函式沒有引數,但可能丟擲異常。
32fs.unlinkSync(path)
同步 unlink().
33fs.rmdir(path, callback)
非同步 rmdir().回撥函式沒有引數,但可能丟擲異常。
34fs.rmdirSync(path)
同步 rmdir().
35fs.mkdir(path[, mode], callback)
S非同步 mkdir(2).回撥函式沒有引數,但可能丟擲異常。 訪問許可權預設為 0777。
36fs.mkdirSync(path[, mode])
同步 mkdir().
37fs.readdir(path, callback)
非同步 readdir(3). 讀取目錄的內容。
38fs.readdirSync(path)
同步 readdir().返回檔案陣列列表。
39fs.close(fd, callback)
非同步 close().回撥函式沒有引數,但可能丟擲異常。
40fs.closeSync(fd)
同步 close().
41fs.open(path, flags[, mode], callback)
非同步開啟檔案。
42fs.openSync(path, flags[, mode])
同步 version of fs.open().
43fs.utimes(path, atime, mtime, callback)
 
44fs.utimesSync(path, atime, mtime)
修改檔案時間戳,檔案通過指定的檔案路徑。
45fs.futimes(fd, atime, mtime, callback)
 
46fs.futimesSync(fd, atime, mtime)
修改檔案時間戳,通過檔案描述符指定。
47fs.fsync(fd, callback)
非同步 fsync.回撥函式沒有引數,但可能丟擲異常。
48fs.fsyncSync(fd)
同步 fsync.
49fs.write(fd, buffer, offset, length[, position], callback)
將緩衝區內容寫入到通過檔案描述符指定的檔案。
50fs.write(fd, data[, position[, encoding]], callback)
通過檔案描述符 fd 寫入檔案內容。
51fs.writeSync(fd, buffer, offset, length[, position])
同步版的 fs.write()。
52fs.writeSync(fd, data[, position[, encoding]])
同步版的 fs.write().
53fs.read(fd, buffer, offset, length, position, callback)
通過檔案描述符 fd 讀取檔案內容。
54fs.readSync(fd, buffer, offset, length, position)
同步版的 fs.read.
55fs.readFile(filename[, options], callback)
非同步讀取檔案內容。
56fs.readFileSync(filename[, options])
57fs.writeFile(filename, data[, options], callback)
非同步寫入檔案內容。
58fs.writeFileSync(filename, data[, options])
同步版的 fs.writeFile。
59fs.appendFile(filename, data[, options], callback)
非同步追加檔案內容。
60fs.appendFileSync(filename, data[, options])
The 同步 version of fs.appendFile.
61fs.watchFile(filename[, options], listener)
檢視檔案的修改。
62fs.unwatchFile(filename[, listener])
停止檢視 filename 的修改。
63fs.watch(filename[, options][, listener])
檢視 filename 的修改,filename 可以是檔案或目錄。返回 fs.FSWatcher 物件。
64fs.exists(path, callback)
檢測給定的路徑是否存在。
65fs.existsSync(path)
同步版的 fs.exists.
66fs.access(path[, mode], callback)
測試指定路徑使用者許可權。
67fs.accessSync(path[, mode])
同步版的 fs.access。
68fs.createReadStream(path[, options])
返回ReadStream 物件。
69fs.createWriteStream(path[, options])
返回 WriteStream 物件。
70fs.symlink(srcpath, dstpath[, type], callback)
非同步 symlink().回撥函式沒有引數,但可能丟擲異常。

更多內容,請檢視官網檔案模組描述:File System。