使用nodeJS中的fs模塊對(duì)文件及目錄進(jìn)行讀寫(xiě),刪除,追加,等操作詳解
fs概述
文件 I/O 是由簡(jiǎn)單封裝的標(biāo)準(zhǔn) POSIX 函數(shù)提供的。 nodeJS中通過(guò) require('fs') 使用fs模塊。 所有的方法都有異步和同步的形式。
異步形式始終以完成回調(diào)作為它最后一個(gè)參數(shù)。 傳給完成回調(diào)的參數(shù)取決于具體方法,但第一個(gè)參數(shù)總是留給異常。 如果操作成功完成,則第一個(gè)參數(shù)會(huì)是 null 或 undefined
//異步示例 var fs = require('fs'); fs.unlink('/tmp/hello', function(err){ if (err) throw err; console.log('successfully deleted /tmp/hello'); });
當(dāng)使用同步形式時(shí),任何異常都會(huì)被立即拋出。 可以使用 try/catch 來(lái)處理異常,或讓它們往上冒泡
//同步示例 var fs = require('fs'); fs.unlinkSync('/tmp/hello'); console.log('successfully deleted /tmp/hello');
異步方法不保證執(zhí)行順序。 所以下面的例子容易出錯(cuò)
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.stat 可能在 fs.rename 之前執(zhí)行。正確的方法是把回調(diào)鏈起來(lái)
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)}'); }); });
推薦開(kāi)發(fā)者使用這些函數(shù)的異步版本。 同步版本會(huì)阻塞整個(gè)進(jìn)程,直到它們完成(停止所有連接)
fs底層操作
1、打開(kāi)文件 fs.open(path, flags[, mode], callback)
參數(shù)如下:
path <String> | <Buffer>
flags <String> | <Number>
mode <Integer> 設(shè)置文件模式(權(quán)限和 sticky 位),但只有當(dāng)文件被創(chuàng)建時(shí)才有效。默認(rèn)為 0666,可讀寫(xiě)
callback <Function> 該回調(diào)有兩個(gè)參數(shù) (err錯(cuò)誤, fd文件標(biāo)識(shí),與定時(shí)器標(biāo)識(shí)類(lèi)似)
flags可以是:
'r' - 以讀取模式打開(kāi)文件。如果文件不存在則發(fā)生異常。
'r+' - 以讀寫(xiě)模式打開(kāi)文件。如果文件不存在則發(fā)生異常。
'rs+' - 以同步讀寫(xiě)模式打開(kāi)文件。命令操作系統(tǒng)繞過(guò)本地文件系統(tǒng)緩存。
'w' - 以寫(xiě)入模式打開(kāi)文件。文件會(huì)被創(chuàng)建(如果文件不存在)或截?cái)?如果文件存在)。
'wx' - 類(lèi)似 'w',但如果 path 存在,則失敗。
'w+' - 以讀寫(xiě)模式打開(kāi)文件。文件會(huì)被創(chuàng)建(如果文件不存在)或截?cái)?如果文件存在)。
'wx+' - 類(lèi)似 'w+',但如果 path 存在,則失敗。
'a' - 以追加模式打開(kāi)文件。如果文件不存在,則會(huì)被創(chuàng)建。
'ax' - 類(lèi)似于 'a',但如果 path 存在,則失敗。
'a+' - 以讀取和追加模式打開(kāi)文件。如果文件不存在,則會(huì)被創(chuàng)建。
'ax+' - 類(lèi)似于 'a+',但如果 path 存在,則失敗。
[注意]使用'rs+'模式不會(huì)使fs.open()進(jìn)入同步阻塞調(diào)用。如果那是你想要的,則應(yīng)該使用fs.openSync()
var fs = require('fs'); fs.open('a.txt','r',function(err,fs){ console.log(err);//null console.log(fs);//3 })
var fs = require('fs'); fs.open('b.txt','r',function(err,fs){ /* { Error: ENOENT: no such file or directory, open 'D:\project\b.txt' at Error (native) errno: -4058, code: 'ENOENT', syscall: 'open', path: 'D:\\project\\b.txt' } */ console.log(err); console.log(fs);//undefined })
文件的回調(diào)函數(shù)中的第二個(gè)參數(shù)fd代表文件標(biāo)識(shí),與定時(shí)器標(biāo)識(shí)類(lèi)似,用于標(biāo)識(shí)文件,且隨著文件的打開(kāi)順序遞增
var fs = require('fs'); fs.open('1.txt','r',function(err,fs){ console.log(fs);//3 }) fs.open('2.txt','r',function(err,fs){ console.log(fs);//4 })
fs.openSync(path, flags[, mode])
fs.open() 的同步版本。 返回一個(gè)表示文件描述符的整數(shù)
var fs = require('fs'); var result = fs.openSync('1.txt','r'); console.log(result);//3
2、讀取文件 fs.read(fd, buffer, offset, length, position, callback)
參數(shù)如下:
fd <Integer> 通過(guò) fs.open() 方法返回的文件描述符
buffer <String> | <Buffer> 數(shù)據(jù)將被寫(xiě)入到buffer
offset <Integer> buffer中開(kāi)始寫(xiě)入的偏移量
length <Integer> 指定要讀取的字節(jié)數(shù)(整數(shù))
position <Integer> 指定從文件中開(kāi)始讀取的位置(整數(shù))。 如果position為null,則數(shù)據(jù)從當(dāng)前文件位置開(kāi)始讀取
callback <Function> 回調(diào)有三個(gè)參數(shù) (err, bytesRead, buffer)。err為錯(cuò)誤信息,bytesRead表示讀取的字節(jié)數(shù),buffer為緩沖區(qū)對(duì)象
由于使用read()方法,會(huì)將文件內(nèi)容讀取buffer對(duì)象中,所以需要提前先準(zhǔn)備一個(gè)buffer對(duì)象
var fs = require('fs'); fs.open('1.txt','r',function(err,fd){ if(err){ console.log('文件打開(kāi)失敗'); }else{ var bf = Buffer.alloc(5); fs.read(fd,bf,0,3,null,function(err,len,buffer){ console.log(err);//null console.log(len);//3 console.log(buffer);//<Buffer 61 61 61 00 00> }) } });
fs.readSync(fd, buffer, offset, length, position)
fs.read() 的同步版本,返回 bytesRead 的數(shù)量
var fs = require('fs'); var fd = fs.openSync('1.txt','r'); var bf = Buffer.alloc(5); var result = fs.readSync(fd,bf,0,3,null); console.log(result);//3
3、寫(xiě)入文件 fs.write(fd, buffer, offset, length[, position], callback)
參數(shù)如下
fd <Integer> 文件標(biāo)識(shí)
buffer <String> | <Buffer> 要將buffer中的數(shù)據(jù)寫(xiě)入到文件中
offset <Integer> buffer對(duì)象中要寫(xiě)入的數(shù)據(jù)的起始位置
length <Integer> length是一個(gè)整數(shù),指定要寫(xiě)入的字節(jié)數(shù)
position <Integer> 指定從文件開(kāi)始寫(xiě)入數(shù)據(jù)的位置的偏移量。 如果 typeof position !== 'number',則數(shù)據(jù)從當(dāng)前位置寫(xiě)入
callback <Function> 回調(diào)有三個(gè)參數(shù)(err, written, buffer),其中written指定從buffer寫(xiě)入了多少字節(jié)
[注意]多次對(duì)同一文件使用fs.write且不等待回調(diào),是不安全的。對(duì)于這種情況,強(qiáng)烈推薦使用 fs.createWriteStream
當(dāng)我們要對(duì)打開(kāi)的文件進(jìn)行寫(xiě)操作的時(shí)候,打開(kāi)文件的模式應(yīng)該是讀寫(xiě)模式
var fs = require('fs'); fs.open('1.txt','r+',function(err,fd){ if(err){ console.log('文件打開(kāi)失敗'); }else{ var bf = Buffer.from('test'); fs.write(fd,bf,0,3,null,function(err,len,buffer){ console.log(err);//null console.log(len);//3 console.log(buffer);//<Buffer 74 65 73 74> }) } });
fs.write(fd, data[, position[, encoding]], callback)
該方法寫(xiě)入data到fd指定的文件。如果data不是一個(gè)Buffer實(shí)例,則該值將被強(qiáng)制轉(zhuǎn)換為一個(gè)字符串
不同于寫(xiě)入 buffer,該方法整個(gè)字符串必須被寫(xiě)入。不能指定子字符串,這是因?yàn)榻Y(jié)果數(shù)據(jù)的字節(jié)偏移量可能與字符串的偏移量不同
fd <Integer> 文件標(biāo)識(shí)
data <String> | <Buffer> 要將string或buffer中的數(shù)據(jù)寫(xiě)入到文件中
position <Integer> 指向從文件開(kāi)始寫(xiě)入數(shù)據(jù)的位置的偏移量。 如果 typeof position !== 'number',則數(shù)據(jù)從當(dāng)前位置寫(xiě)入
encoding <String> 期望的字符串編碼
callback <Function> 回調(diào)有三個(gè)參數(shù)(err, written, str),其中written指定從str寫(xiě)入了多少字節(jié)
var fs = require('fs'); fs.open('1.txt','r+',function(err,fd){ if(err){ console.log('文件打開(kāi)失敗'); }else{ fs.write(fd,'12345',function(err,len,str){ console.log(err);//null console.log(len);//5 console.log(str);//<Buffer 74 65 73 74> }) } });
fs.writeSync()
fs.write() 的同步版本。返回寫(xiě)入的字節(jié)數(shù)
var fs = require('fs'); var fd = fs.openSync('1.txt','r+'); var bf = Buffer.alloc(5); var result = fs.writeSync(fd,bf,0,3,null); console.log(result);//3
4、關(guān)閉文件 fs.close(fd, callback)
一個(gè)文件被操作后,要及時(shí)將該文件關(guān)閉
參數(shù)如下:
fd - 通過(guò) fs.open() 方法返回的文件描述符。
callback - 回調(diào)函數(shù),沒(méi)有參數(shù)。
var fs = require('fs'); fs.open('1.txt','r+',function(err,fd){ if(err){ console.log('文件打開(kāi)失敗'); }else{ fs.close(fd, function(err){ if (err){ console.log(err); } console.log("文件關(guān)閉成功"); }); } });
fs.closeSync(fd)
fs.close(fd, callback)的同步版本,返回undefined
var fs = require('fs'); var fd = fs.openSync('1.txt','r+'); fs.closeSync(fd);
File操作
上一部分介紹的都是些底層的操作,接下來(lái)將介紹一些更便捷的文件操作。使用下列方法的時(shí)候,不需要再打開(kāi)和關(guān)閉文件,直接操作即可
1、寫(xiě)入文件
fs.writeFile(file, data[, options], callback)
異步的將數(shù)據(jù)寫(xiě)入一個(gè)文件,如果文件不存在則新建,如果文件原先存在,會(huì)被替換
參數(shù)如下:
file - 文件名或文件描述符。
data - 要寫(xiě)入文件的數(shù)據(jù),可以是 String(字符串) 或 Buffer(流) 對(duì)象。
options - 該參數(shù)是一個(gè)對(duì)象,包含 {encoding, mode, flag}。默認(rèn)編碼為 utf8, 模式為 0666 , flag 為 'w'
callback - 回調(diào)函數(shù),回調(diào)函數(shù)只包含錯(cuò)誤信息參數(shù)(err),在寫(xiě)入失敗時(shí)返回。
var fs = require('fs'); var filename = '1.txt'; fs.writeFile(filename,'hello',function(err){ console.log(err);//null })
fs.writeFileSync(file, data[, options])
fs.writeFile() 的同步版本。返回 undefined
var fs = require('fs'); var filename = '1.txt'; fs.writeFileSync(filename,'abc');
2、追加文件
fs.appendFile(filename, data, [options], callback)
異步地追加數(shù)據(jù)到一個(gè)文件,如果文件不存在則創(chuàng)建文件。 data 可以是一個(gè)字符串或 buffer
參數(shù)如下
file - 文件名或文件描述符。
data - 要寫(xiě)入文件的數(shù)據(jù),可以是 String(字符串) 或 Buffer(流) 對(duì)象。
options - 該參數(shù)是一個(gè)對(duì)象,包含 {encoding, mode, flag}。默認(rèn)編碼為 utf8, 模式為 0666 , flag 為 'w'
callback - 回調(diào)函數(shù),回調(diào)函數(shù)只包含錯(cuò)誤信息參數(shù)(err),在寫(xiě)入失敗時(shí)返回。
var fs = require('fs'); var filename = '1.txt'; fs.appendFile(filename,' world',function(err){ console.log(err);//null })
fs.appendFileSync(file, data[, options])
fs.appendFile()的同步版本。返回undefined
var fs = require('fs'); var filename = '1.txt'; fs.appendFileSync(filename,' lalala');
3、讀取文件
fs.readFile(file[, options], callback)
參數(shù)如下
file - 文件名或文件描述符
options - 該參數(shù)是一個(gè)對(duì)象,包含 {encoding, flag}。默認(rèn)編碼為null,即如果字符編碼未指定,則返回原始的 buffer;flag默認(rèn)為'r'
callback - 回調(diào)函數(shù),回調(diào)有兩個(gè)參數(shù) (err, data),其中data是文件的內(nèi)容(buffer對(duì)象),err是錯(cuò)誤信息參數(shù),在寫(xiě)入失敗時(shí)返回
var fs = require('fs'); var filename = '1.txt'; fs.readFile(filename,function(err,data){ if(err){ console.log('文件讀取失敗'); }else{ console.log(data);//<Buffer 61 62 63 20 77 6f 72 6c 64 20 6c 61 6c 61 6c 61> console.log(data.toString());//'abc world lalala' } });
fs.readFileSync(file[, options])
fs.readFile的同步版本。返回file的內(nèi)容
如果指定了encoding選項(xiàng),則該函數(shù)返回一個(gè)字符串,否則返回一個(gè)buffer
var fs = require('fs'); var filename = '1.txt'; var result = fs.readFileSync(filename); console.log(result);//<Buffer 61 62 63 20 77 6f 72 6c 64 20 6c 61 6c 61 6c 61> console.log(result.toString());'abc world lalala'
4、刪除文件
fs.unlink(path, callback)
參數(shù)如下:
path - 文件路徑。
callback - 回調(diào)函數(shù),沒(méi)有參數(shù)。
var fs = require('fs'); var filename = '1.txt'; fs.unlink(filename, function(err) { if (err) { return console.log('刪除失敗'); } console.log("刪除成功"); });
fs.unlinkSync(path)
fs.unlink(path, callback)的同步版本,返回值為undefined
var fs = require('fs'); var filename = '1.txt'; fs.unlink(filename);
5、重命名
fs.rename(oldPath, newPath, callback)
參數(shù)如下:
oldPath <String> | <Buffer>
newPath <String> | <Buffer>
callback <Function> 回調(diào)只有一個(gè)可能的異常參數(shù)
var fs = require('fs'); var filename = 'a.txt'; fs.rename(filename,'2.new.txt',function(err){ console.log(err);//null })
fs.renameSync(oldPath, newPath)
fs.rename(oldPath, newPath, callback)的同步版本,返回undefined
var fs = require('fs'); var filename = '2.new.txt'; var result = fs.renameSync(filename,'a.txt');
6、文件信息
fs.stat(path, callback)
fs.stat()執(zhí)行后,會(huì)將stats類(lèi)的實(shí)例返回給其回調(diào)函數(shù)??赏ㄟ^(guò)stats類(lèi)中的提供方法判斷文件的相關(guān)屬性
參數(shù)如下:
path - 文件路徑。
callback - 回調(diào)函數(shù),帶有兩個(gè)參數(shù)如:(err, stats), stats 是 fs.Stats 對(duì)象
var fs = require('fs'); var filename = 'a.txt'; fs.stat(filename,function(err,stats){ console.log(err);//null /* { dev: 223576, mode: 33206, nlink: 1, uid: 0, gid: 0, rdev: 0, blksize: undefined, ino: 7599824371527537, size: 0, blocks: undefined, atime: 2017-06-03T14:18:15.370Z, mtime: 2017-06-03T14:18:15.370Z, ctime: 2017-06-03T16:32:05.776Z, birthtime: 2017-06-03T14:18:15.370Z } */ console.log(stats); });
stats類(lèi)中的方法有
stats.isFile() 如果是文件返回 true,否則返回 false。
stats.isDirectory() 如果是目錄返回 true,否則返回 false。
stats.isBlockDevice() 如果是塊設(shè)備返回 true,否則返回 false。
stats.isCharacterDevice() 如果是字符設(shè)備返回 true,否則返回 false。
stats.isSymbolicLink() 如果是軟鏈接返回 true,否則返回 false。
stats.isFIFO() 如果是FIFO,返回true,否則返回false。FIFO是UNIX中的一種特殊類(lèi)型的命令管道。
stats.isSocket() 如果是 Socket 返回 true,否則返回 false。
var fs = require('fs'); var filename = 'a.txt'; fs.stat(filename,function(err,stats){ console.log(stats.isFile());//true });
fs.statSync(path)
fs.stat(path, callback)方法的同步版本,返回一個(gè) fs.Stats 實(shí)例
var fs = require('fs'); var filename = 'a.txt'; var result = fs.statSync(filename); /* { dev: 223576, mode: 33206, nlink: 1, uid: 0, gid: 0, rdev: 0, blksize: undefined, ino: 7599824371527537, size: 0, blocks: undefined, atime: 2017-06-03T14:18:15.370Z, mtime: 2017-06-03T14:18:15.370Z, ctime: 2017-06-03T16:32:05.776Z, birthtime: 2017-06-03T14:18:15.370Z } */ console.log(result);
7、監(jiān)聽(tīng)
fs.watch(filename[, options][, listener])
該方法用于監(jiān)視filename的變化,filename可以是一個(gè)文件或一個(gè)目錄。返回的對(duì)象是一個(gè)fs.FSWatcher
參數(shù)如下
filename <String> | <Buffer>
options <String> | <Object> 參數(shù)可選,如果options是一個(gè)字符串,則它指定了encoding。否則options應(yīng)該以一個(gè)對(duì)象傳入
persistent <Boolean> 指明如果文件正在被監(jiān)視,進(jìn)程是否應(yīng)該繼續(xù)運(yùn)行。默認(rèn)為true
recursive <Boolean> 指明是否全部子目錄應(yīng)該被監(jiān)視,或只是當(dāng)前目錄。 適用于當(dāng)一個(gè)目錄被指定時(shí),且只在支持的平臺(tái)。默認(rèn)為false
encoding <String> 指定用于傳給監(jiān)聽(tīng)器的文件名的字符編碼。默認(rèn)為'utf8'
listener <Function> 回調(diào)函數(shù)有兩個(gè)參數(shù) (eventType, filename)。 eventType可以是'rename'或'change',filename是觸發(fā)事件的文件的名稱(chēng)
回調(diào)中提供的 filename 參數(shù)僅在 Linux 和 Windows 系統(tǒng)上支持。 即使在支持的平臺(tái)中,filename 也不能保證提供。 因此,不要以為 filename 參數(shù)總是在回調(diào)中提供,如果它是空的,需要有一定的后備邏輯
fs.watch('somedir', (eventType, filename) => { console.log(`事件類(lèi)型是: ${eventType}`); if (filename) { console.log(`提供的文件名: ${filename}`); } else { console.log('未提供文件名'); } });
var fs = require('fs'); var filename = '1.txt'; fs.watch(filename,function(eventType, _filename){ console.log(eventType);//change if(_filename){ console.log(_filename + '發(fā)生了改變');//'1.txt發(fā)生了改變' }else{ console.log('...'); } })
[注意]當(dāng)一個(gè)文件出現(xiàn)或消失在一個(gè)目錄里時(shí),'rename'也會(huì)被觸發(fā)
fs目錄操作
1、創(chuàng)建
fs.mkdir(path[, mode], callback)
參數(shù)如下:
path - 文件路徑。
mode - 設(shè)置目錄權(quán)限,默認(rèn)為 0777。
callback - 回調(diào)函數(shù),回調(diào)只有一個(gè)可能的異常參數(shù)
var fs = require('fs'); fs.mkdir('./1',function(err){ console.log(err);//null })
fs.mkdirSync(path[, mode])
fs.mkdir(path[, mode], callback)的同步版本,返回undefined
var fs = require('fs'); fs.mkdirSync('./2');
2、刪除
fs.rmdir(path, callback)
參數(shù)如下:
path - 文件路徑。
callback - 回調(diào)函數(shù),回調(diào)只有一個(gè)可能的異常參數(shù)
var fs = require('fs'); fs.rmdir('./1',function(err){ console.log(err);//null })
fs.rmdirSync(path, callback)
fs.rmdir(path, callback)的同步版本,返回undefined
var fs = require('fs'); fs.rmdirSync('./2');
3、讀取
fs.readdir(path[, options], callback)
參數(shù)如下:
path <String> | <Buffer>
options <String> | <Object> 可選的 options 參數(shù)用于傳入回調(diào)的文件名,它可以是一個(gè)字符串并指定一個(gè)字符編碼,或是一個(gè)對(duì)象且由一個(gè) encoding 屬性指定使用的字符編碼。 如果 encoding 設(shè)為 'buffer',則返回的文件名會(huì)被作為 Buffer 對(duì)象傳入
encoding <String> 默認(rèn) = 'utf8'
callback <Function> 回調(diào)有兩個(gè)參數(shù) (err, files),其中 files 是目錄中不包括 '.' 和 '..' 的文件名的數(shù)組
var fs = require('fs'); fs.readdir('./',function(err,data){ console.log(err);//null /* [ '.csslintrc', '.jshintrc', 'a.txt', 'dist', 'Gruntfile.js', 'Gruntfile1.js', 'index.html', 'main.js', 'node_modules', 'package.json', 'src' ] */ console.log(data); })
var fs = require('fs'); fs.readdir('./',function(err,data){ data.forEach(function(item,index,arr){ fs.stat(item,function(err,stats){ if(stats.isFile()){ console.log('文件:' + item); } if(stats.isDirectory()){ console.log('目錄:' + item); } }); }) }) /* 文件:.jshintrc 文件:.csslintrc 目錄:dist 文件:Gruntfile.js 文件:index.html 文件:Gruntfile1.js 文件:main.js 目錄:node_modules 文件:package.json 文件:a.txt 目錄:src */
fs.readdirSync(path[, options], callback)
fs.readdir(path[, options], callback)的同步版本,返回一個(gè)不包括 '.' 和 '..' 的文件名的數(shù)組
var fs = require('fs'); var result = fs.readdirSync('./'); /* [ '.csslintrc', '.jshintrc', 'a.txt', 'dist', 'Gruntfile.js', 'Gruntfile1.js', 'index.html', 'main.js', 'node_modules', 'package.json', 'src' ] */ console.log(result);
遍歷目錄
遍歷目錄是操作文件時(shí)的一個(gè)常見(jiàn)需求。比如寫(xiě)一個(gè)程序,需要找到并處理指定目錄下的所有JS文件時(shí),就需要遍歷整個(gè)目錄
遍歷目錄時(shí)一般使用遞歸算法,否則就難以編寫(xiě)出簡(jiǎn)潔的代碼。遞歸算法與數(shù)學(xué)歸納法類(lèi)似,通過(guò)不斷縮小問(wèn)題的規(guī)模來(lái)解決問(wèn)題
function factorial(n) { if (n === 1) { return 1; } else { return n * factorial(n - 1); } }
上邊的函數(shù)用于計(jì)算N的階乘(N!)??梢钥吹剑?dāng)N大于1時(shí),問(wèn)題簡(jiǎn)化為計(jì)算N乘以N-1的階乘。當(dāng)N等于1時(shí),問(wèn)題達(dá)到最小規(guī)模,不需要再簡(jiǎn)化,因此直接返回1
目錄是一個(gè)樹(shù)狀結(jié)構(gòu),在遍歷時(shí)一般使用深度優(yōu)先+先序遍歷算法。深度優(yōu)先,意味著到達(dá)一個(gè)節(jié)點(diǎn)后,首先接著遍歷子節(jié)點(diǎn)而不是鄰居節(jié)點(diǎn)。先序遍歷,意味著首次到達(dá)了某節(jié)點(diǎn)就算遍歷完成,而不是最后一次返回某節(jié)點(diǎn)才算數(shù)。因此使用這種遍歷方式時(shí),下邊這棵樹(shù)的遍歷順序是A > B > D > E > C > F
A
/ \
B C
/ \ \
D E F
了解了必要的算法后,我們可以簡(jiǎn)單地實(shí)現(xiàn)以下目錄遍歷函數(shù)
function travel(dir, callback) { fs.readdirSync(dir).forEach(function (file) { var pathname = path.join(dir, file); if (fs.statSync(pathname).isDirectory()) { travel(pathname, callback); } else { callback(pathname); } }); }
可以看到,該函數(shù)以某個(gè)目錄作為遍歷的起點(diǎn)。遇到一個(gè)子目錄時(shí),就先接著遍歷子目錄。遇到一個(gè)文件時(shí),就把文件的絕對(duì)路徑傳給回調(diào)函數(shù)。回調(diào)函數(shù)拿到文件路徑后,就可以做各種判斷和處理。因此假設(shè)有以下目錄
- /home/user/
- foo/
x.js
- bar/
y.js
z.css
使用以下代碼遍歷該目錄時(shí),得到的輸入如下
travel('/home/user', function (pathname) { console.log(pathname); }); ------------------------ /home/user/foo/x.js /home/user/bar/y.js /home/user/z.css
如果讀取目錄或讀取文件狀態(tài)時(shí)使用的是異步API,目錄遍歷函數(shù)實(shí)現(xiàn)起來(lái)會(huì)有些復(fù)雜,但原理完全相同。travel函數(shù)的異步版本如下
function travel(dir, callback, finish) { fs.readdir(dir, function (err, files) { (function next(i) { if (i < files.length) { var pathname = path.join(dir, files[i]); fs.stat(pathname, function (err, stats) { if (stats.isDirectory()) { travel(pathname, callback, function () { next(i + 1); }); } else { callback(pathname, function () { next(i + 1); }); } }); } else { finish && finish(); } }(0)); });
更多關(guān)于nodeJS中fs模塊對(duì)文件及目錄進(jìn)行讀寫(xiě),刪除,追加,等操作的相關(guān)文章大家可以查看下面的相關(guān)鏈接
相關(guān)文章
Node.js Buffer模塊功能及常用方法實(shí)例分析
這篇文章主要介紹了Node.js Buffer模塊功能及常用方法,結(jié)合實(shí)例形式分析了Buffer模塊的各種常用函數(shù)及相關(guān)使用技巧,需要的朋友可以參考下2019-01-01Node.js參數(shù)校驗(yàn)?zāi)Kminijoi使用詳解
這篇文章主要為大家介紹了Node.js參數(shù)校驗(yàn)?zāi)Kminijoi使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-09-09node.js中的fs.createWriteStream方法使用說(shuō)明
這篇文章主要介紹了node.js中的fs.createWriteStream方法使用說(shuō)明,本文介紹了fs.createWriteStream方法說(shuō)明、語(yǔ)法、接收參數(shù)、使用實(shí)例和實(shí)現(xiàn)源碼,需要的朋友可以參考下2014-12-12nodejs+express實(shí)現(xiàn)文件上傳下載管理網(wǎng)站
這篇文章主要為大家詳細(xì)介紹了nodejs+express實(shí)現(xiàn)文件上傳下載管理的網(wǎng)站,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-03-03使用iojs的jsdom庫(kù)實(shí)現(xiàn)同步系統(tǒng)時(shí)間
本文給大家分享的是使用iojs的jsdom庫(kù)實(shí)現(xiàn)與http://open.baidu.com/special/time/ 同步系統(tǒng)時(shí)間。思路非常的清晰,這里推薦給大家,有需要的小伙伴可以參考下。2015-04-04nodejs開(kāi)發(fā)一個(gè)最簡(jiǎn)單的web服務(wù)器實(shí)例講解
在本篇文章里小編給大家整理的是關(guān)于nodejs開(kāi)發(fā)一個(gè)最簡(jiǎn)單的web服務(wù)器實(shí)例內(nèi)容,有需要的朋友們可以參考下。2020-01-01node省市區(qū)三級(jí)數(shù)據(jù)性能測(cè)評(píng)實(shí)例分析
這篇文章主要介紹了node省市區(qū)三級(jí)數(shù)據(jù)性能,結(jié)合具體實(shí)例形式評(píng)測(cè)分析了node省市區(qū)三級(jí)數(shù)據(jù)的實(shí)現(xiàn)、改進(jìn)方法與運(yùn)行效率,需要的朋友可以參考下2019-11-11nodejs實(shí)現(xiàn)百度輿情接口應(yīng)用示例
這篇文章主要介紹了nodejs實(shí)現(xiàn)百度輿情接口應(yīng)用,結(jié)合實(shí)例形式分析了node.js調(diào)用百度輿情接口的具體使用技巧,需要的朋友可以參考下2020-02-02