//公共引用
var fs = require('fs'),
path = require('path');
//readFile(filename,[options],callback);
/**
* filename, 必選參數,文件名
* [options],可選參數,可指定flag(文件操做選項,如r+ 讀寫;w+ 讀寫,文件不存在則建立)及encoding屬性
* callback 讀取文件後的回調函數,參數默認第一個err,第二個data 數據
*/
fs.readFile(__dirname + '/test.txt', {flag: 'r+', encoding: 'utf8'}, function (err, data) {
if(err) {
console.error(err);
return;
}
console.log(data);
});
// fs.writeFile(filename,data,[options],callback); var w_data = '這是一段經過fs.writeFile函數寫入的內容;\r\n'; var w_data = new Buffer(w_data); /** * filename, 必選參數,文件名 * data, 寫入的數據,能夠字符或一個Buffer對象 * [options],flag,mode(權限),encoding * callback 讀取文件後的回調函數,參數默認第一個err,第二個data 數據 */ fs.writeFile(__dirname + '/test.txt', w_data, {flag: 'a'}, function (err) { if(err) { console.error(err); } else { console.log('寫入成功'); } });
// fs.appendFile(filename,data,[options],callback); fs.appendFile(__dirname + '/test.txt', '使用fs.appendFile追加文件內容', function () { console.log('追加內容完成'); });
// fs.open(filename, flags, [mode], callback); /** * filename, 必選參數,文件名 * flags, 操做標識,如"r",讀方式打開 * [mode],權限,如777,表示任何用戶讀寫可執行 * callback 打開文件後回調函數,參數默認第一個err,第二個fd爲一個整數,表示打開文件返回的文件描述符,window中又稱文件句柄 */ fs.open(__dirname + '/test.txt', 'r', '0666', function (err, fd) { console.log(fd); });
//fs.read(fd, buffer, offset, length, position, callback); /** * fd, 使用fs.open打開成功後返回的文件描述符 * buffer, 一個Buffer對象,v8引擎分配的一段內存 * offset, 整數,向緩存區中寫入時的初始位置,以字節爲單位 * length, 整數,讀取文件的長度 * position, 整數,讀取文件初始位置;文件大小以字節爲單位 * callback(err, bytesRead, buffer), 讀取執行完成後回調函數,bytesRead實際讀取字節數,被讀取的緩存區對象 */ fs.open(__dirname + '/test.txt', 'r', function (err, fd) { if(err) { console.error(err); return; } else { var buffer = new Buffer(255); console.log(buffer.length); //每個漢字utf8編碼是3個字節,英文是1個字節 fs.read(fd, buffer, 0, 9, 3, function (err, bytesRead, buffer) { if(err) { throw err; } else { console.log(bytesRead); console.log(buffer.slice(0, bytesRead).toString()); //讀取完後,再使用fd讀取時,基點是基於上次讀取位置計算; fs.read(fd, buffer, 0, 9, null, function (err, bytesRead, buffer) { console.log(bytesRead); console.log(buffer.slice(0, bytesRead).toString()); }); } }); } });
//fs.write(fd, buffer, offset, length, position, callback); /** * fd, 使用fs.open打開成功後返回的文件描述符 * buffer, 一個Buffer對象,v8引擎分配的一段內存 * offset, 整數,從緩存區中讀取時的初始位置,以字節爲單位 * length, 整數,從緩存區中讀取數據的字節數 * position, 整數,寫入文件初始位置; * callback(err, written, buffer), 寫入操做執行完成後回調函數,written實際寫入字節數,buffer被讀取的緩存區對象 */ fs.open(__dirname + '/test.txt', 'a', function (err, fd) { if(err) { console.error(err); return; } else { var buffer = new Buffer('寫入文件數據內容'); //寫入'入文件'三個字 fs.write(fd, buffer, 3, 9, 12, function (err, written, buffer) { if(err) { console.log('寫入文件失敗'); console.error(err); return; } else { console.log(buffer.toString()); //寫入'數據內'三個字 fs.write(fd, buffer, 12, 9, null, function (err, written, buffer) { console.log(buffer.toString()); }) } }); } });
// 使用fs.write寫入文件時,操做系統是將數據讀到內存,再把數據寫入到文件中,當數據讀完時並不表明數據已經寫完,由於有一部分還可能在內在緩衝區內。 // 所以可使用fs.fsync方法將內存中數據寫入文件;--刷新內存緩衝區; //fs.fsync(fd, [callback]) /** * fd, 使用fs.open打開成功後返回的文件描述符 * [callback(err, written, buffer)], 寫入操做執行完成後回調函數,written實際寫入字節數,buffer被讀取的緩存區對象 */ fs.open(__dirname + '/test.txt', 'a', function (err, fd) { if(err) throw err; var buffer = new Buffer('我愛nodejs編程'); fs.write(fd, buffer, 0, 9, 0, function (err, written, buffer) { console.log(written.toString()); fs.write(fd, buffer, 9, buffer.length - 9, null, function (err, written) { console.log(written.toString()); fs.fsync(fd); fs.close(fd); }) }); });
//使用fs.mkdir建立目錄 //fs.mkdir(path, [mode], callback); /** * path, 被建立目錄的完整路徑及目錄名; * [mode], 目錄權限,默認0777 * [callback(err)], 建立完目錄回調函數,err錯誤對象 */ fs.mkdir(__dirname + '/fsDir', function (err) { if(err) throw err; console.log('建立目錄成功') });
//使用fs.readdir讀取目錄,重點其回調函數中files對象 //fs.readdir(path, callback); /** * path, 要讀取目錄的完整路徑及目錄名; * [callback(err, files)], 讀完目錄回調函數;err錯誤對象,files數組,存放讀取到的目錄中的全部文件名 */ fs.readdir(__dirname + '/fsDir/', function (err, files) { if(err) { console.error(err); return; } else { files.forEach(function (file) { var filePath = path.normalize(__dirname + '/fsDir/' + file); fs.stat(filePath, function (err, stat) { if(stat.isFile()) { console.log(filePath + ' is: ' + 'file'); } if(stat.isDirectory()) { console.log(filePath + ' is: ' + 'dir'); } }); }); for (var i = 0; i < files.length; i++) { //使用閉包沒法保證讀取文件的順序與數組中保存的致 (function () { var filePath = path.normalize(__dirname + '/fsDir/' + files[i]); fs.stat(filePath, function (err, stat) { if(stat.isFile()) { console.log(filePath + ' is: ' + 'file'); } if(stat.isDirectory()) { console.log(filePath + ' is: ' + 'dir'); } }); })(); } } }); 十、查看文件與目錄的信息; //fs.stat(path, callback); //fs.lstat(path, callback); //查看符號連接文件 /** * path, 要查看目錄/文件的完整路徑及名; * [callback(err, stats)], 操做完成回調函數;err錯誤對象,stat fs.Stat一個對象實例,提供如:isFile, isDirectory,isBlockDevice等方法及size,ctime,mtime等屬性 */ //實例,查看fs.readdir
//fs.exists(path, callback); /** * path, 要查看目錄/文件的完整路徑及名; * [callback(exists)], 操做完成回調函數;exists true存在,false表示不存在 */ fs.exists(__dirname + '/te', function (exists) { var retTxt = exists ? retTxt = '文件存在' : '文件不存在'; console.log(retTxt); });
//fs.utimes(path, atime, mtime, callback); /** * path, 要查看目錄/文件的完整路徑及名; * atime, 新的訪問時間 * ctime, 新的修改時間 * [callback(err)], 操做完成回調函數;err操做失敗對象 */ fs.utimes(__dirname + '/test.txt', new Date(), new Date(), function (err) { if(err) { console.error(err); return; } fs.stat(__dirname + '/test.txt', function (err, stat) { console.log('訪問時間: ' + stat.atime.toString() + '; \n修改時間:' + stat.mtime); console.log(stat.mode); }) });
//fs.utimes(path, mode, callback); /** * path, 要查看目錄/文件的完整路徑及名; * mode, 指定權限,如:0666 8進制,權限:全部用戶可讀、寫, * [callback(err)], 操做完成回調函數;err操做失敗對象 */ fs.chmod(__dirname + '/fsDir', 0666, function (err) { if(err) { console.error(err); return; } console.log('修改權限成功') });
//fs.rename(oldPath, newPath, callback); /** * oldPath, 原目錄/文件的完整路徑及名; * newPath, 新目錄/文件的完整路徑及名;若是新路徑與原路徑相同,而只文件名不一樣,則是重命名 * [callback(err)], 操做完成回調函數;err操做失敗對象 */ fs.rename(__dirname + '/test', __dirname + '/fsDir', function (err) { if(err) { console.error(err); return; } console.log('重命名成功') });
//fs.rmdir(path, callback); /** * path, 目錄的完整路徑及目錄名; * [callback(err)], 操做完成回調函數;err操做失敗對象 */ fs.rmdir(__dirname + '/test', function (err) { fs.mkdir(__dirname + '/test', 0666, function (err) { console.log('建立test目錄'); }); if(err) { console.log('刪除空目錄失敗,可能緣由:一、目錄不存在,二、目錄不爲空') console.error(err); return; } console.log('刪除空目錄成功!'); });
//對文件進行監視,而且在監視到文件被修改時執行處理 //fs.watchFile(filename, [options], listener); /** * filename, 完整路徑及文件名; * [options], persistent true表示持續監視,不退出程序;interval 單位毫秒,表示每隔多少毫秒監視一次文件 * listener, 文件發生變化時回調,有兩個參數:curr爲一個fs.Stat對象,被修改後文件,prev,一個fs.Stat對象,表示修改前對象 */ fs.watchFile(__dirname + '/test.txt', {interval: 20}, function (curr, prev) { if(Date.parse(prev.ctime) == 0) { console.log('文件被建立!'); } else if(Date.parse(curr.ctime) == 0) { console.log('文件被刪除!') } else if(Date.parse(curr.mtime) != Date.parse(prev.mtime)) { console.log('文件有修改'); } }); fs.watchFile(__dirname + '/test.txt', function (curr, prev) { console.log('這是第二個watch,監視到文件有修改'); });
//取消對文件進行監視 //fs.unwatchFile(filename, [listener]); /** * filename, 完整路徑及文件名; * [listener], 要取消的監聽器事件,若是不指定,則取消全部監聽處理事件 */ var listener = function (curr, prev) { console.log('我是監視函數') } fs.unwatchFile(__dirname + '/test.txt', listener);
// 對文件或目錄進行監視,而且在監視到修改時執行處理; // fs.watch返回一個fs.FSWatcher對象,擁有一個close方法,用於中止watch操做; // 當fs.watch有文件變化時,會觸發fs.FSWatcher對象的change(err, filename)事件,err錯誤對象,filename發生變化的文件名 // fs.watch(filename, [options], [listener]); /** * filename, 完整路徑及文件名或目錄名; * [listener(event, filename], 監聽器事件,有兩個參數:event 爲rename表示指定的文件或目錄中有重命名、刪除或移動操做或change表示有修改,filename表示發生變化的文件路徑 */ var fsWatcher = fs.watch(__dirname + '/test', function (event, filename) { //console.log(event) }); //console.log(fsWatcher instanceof FSWatcher); fsWatcher.on('change', function (event, filename) { console.log(filename + ' 發生變化') }); //30秒後關閉監視 setTimeout(function () { console.log('關閉') fsWatcher.close(function (err) { if(err) { console.error(err) } console.log('關閉watch') }); }, 30000);
/* * 流,在應用程序中表示一組有序的、有起點有終點的字節數據的傳輸手段; * Node.js中實現了stream.Readable/stream.Writeable接口的對象進行流數據讀寫;以上接口都繼承自EventEmitter類,所以在讀/寫流不一樣狀態時,觸發不一樣事件; * 關於流讀取:Node.js不斷將文件一小塊內容讀入緩衝區,再從緩衝區中讀取內容; * 關於流寫入:Node.js不斷將流數據寫入內在緩衝區,待緩衝區滿後再將緩衝區寫入到文件中;重複上面操做直到要寫入內容寫寫完; * readFile、read、writeFile、write都是將整個文件放入內存而再操做,而則是文件一部分數據一部分數據操做; * * -----------------------流讀取------------------------------------- * 讀取數據對象: * fs.ReadStream 讀取文件 * http.IncomingMessage 客戶端請求或服務器端響應 * net.Socket Socket端口對象 * child.stdout 子進程標準輸出 * child.stdin 子進程標準入 * process.stdin 用於建立進程標準輸入流 * Gzip、Deflate、DeflateRaw 數據壓縮 * * 觸發事件: * readable 數據可讀時 * data 數據讀取後 * end 數據讀取完成時 * error 數據讀取錯誤時 * close 關閉流對象時 * * 讀取數據的對象操做方法: * read 讀取數據方法 * setEncoding 設置讀取數據的編 * pause 通知對象衆目中止觸發data事件 * resume 通知對象恢復觸發data事件 * pipe 設置數據通道,將讀入流數據接入寫入流; * unpipe 取消通道 * unshift 當流數據綁定一個解析器時,此方法取消解析器 * * ------------------------流寫入------------------------------------- * 寫數據對象: * fs.WriteStream 寫入文件對象 * http.clientRequest 寫入HTTP客戶端請求數據 * http.ServerResponse 寫入HTTP服務器端響應數據 * net.Socket 讀寫TCP流或UNIX流,須要connection事件傳遞給用戶 * child.stdout 子進程標準輸出 * child.stdin 子進程標準入 * Gzip、Deflate、DeflateRaw 數據壓縮 * * 寫入數據觸發事件: * drain 當write方法返回false時,表示緩存區中已經輸出到目標對象中,能夠繼續寫入數據到緩存區 * finish 當end方法調用,所有數據寫入完成 * pipe 當用於讀取數據的對象的pipe方法被調用時 * unpipe 當unpipe方法被調用 * error 當發生錯誤 * * 寫入數據方法: * write 用於寫入數據 * end 結束寫入,以後再寫入會報錯; */
//fs.createReadStream(path, [options]) /** * path 文件路徑 * [options] flags:指定文件操做,默認'r',讀操做;encoding,指定讀取流編碼;autoClose, 是否讀取完成後自動關閉,默認true;start指定文件開始讀取位置;end指定文件開始讀結束位置 */ var rs = fs.createReadStream(__dirname + '/test.txt', {start: 0, end: 2}); //open是ReadStream對象中表示文件打開時事件, rs.on('open', function (fd) { console.log('開始讀取文件'); }); rs.on('data', function (data) { console.log(data.toString()); }); rs.on('end', function () { console.log('讀取文件結束') }); rs.on('close', function () { console.log('文件關閉'); }); rs.on('error', function (err) { console.error(err); }); //暫停和回覆文件讀取; rs.on('open', function () { console.log('開始讀取文件'); }); rs.pause(); rs.on('data', function (data) { console.log(data.toString()); }); setTimeout(function () { rs.resume(); }, 2000);
//fs.createWriteStream(path, [options]) /** * path 文件路徑 * [options] flags:指定文件操做,默認'w',;encoding,指定讀取流編碼;start指定寫入文件的位置 */ /* ws.write(chunk, [encoding], [callback]); * chunk, 能夠爲Buffer對象或一個字符串,要寫入的數據 * [encoding], 編碼 * [callback], 寫入後回調 */ /* ws.end([chunk], [encoding], [callback]); * [chunk], 要寫入的數據 * [encoding], 編碼 * [callback], 寫入後回調 */ var ws = fs.createWriteStream(__dirname + '/test.txt', {start: 0}); var buffer = new Buffer('我也喜歡你'); ws.write(buffer, 'utf8', function (err, buffer) { console.log(arguments); console.log('寫入完成,回調函數沒有參數') }); //最後再寫入的內容 ws.end('再見'); //使用流完成複製文件操做 var rs = fs.createReadStream(__dirname + '/test.txt') var ws = fs.createWriteStream(__dirname + '/test/test.txt'); rs.on('data', function (data) { ws.write(data) }); ws.on('open', function (fd) { console.log('要寫入的數據文件已經打開,文件描述符是: ' + fd); }); rs.on('end', function () { console.log('文件讀取完成'); ws.end('完成', function () { console.log('文件所有寫入完成') }); }); //關於WriteStream對象的write方法返回一個布爾類型,當緩存區中數據所有寫滿時,返回false; //表示緩存區寫滿,並將當即輸出到目標對象中 //第一個例子 var ws = fs.createWriteStream(__dirname + '/test/test.txt'); for (var i = 0; i < 10000; i++) { var w_flag = ws.write(i.toString()); //當緩存區寫滿時,輸出false console.log(w_flag); } //第二個例子 var ws = fs.createWriteStream(__dirname + '/test/untiyou.mp3'); var rs = fs.createReadStream(__dirname + '/test/Until You.mp3'); rs.on('data', function (data) { var flag = ws.write(data); console.log(flag); }); //系統緩存區數據已經所有輸出觸發drain事件 ws.on('drain', function () { console.log('系統緩存區數據已經所有輸出。') });
//rs.pipe(destination, [options]); /** * destination 必須一個可寫入流數據對象 * [opations] end 默認爲true,表示讀取完成當即關閉文件; */ var rs = fs.createReadStream(__dirname + '/test/Until You.mp3'); var ws = fs.createWriteStream(__dirname + '/test/untiyou.mp3'); rs.pipe(ws); rs.on('data', function (data) { console.log('數據可讀') }); rs.on('end', function () { console.log('文件讀取完成'); //ws.end('再見') });