從零學習node.js之文件操作(三)
一、文件操作
在文件操作里,主要是有文件讀寫,創(chuàng)建、移動文件等。
1.1 讀取文件
讀取文本文件時,如.txt, .js, .json等文件,直接使用readFile就可以獲取文件的內(nèi)容。
// server.js
var fs = require('fs');
fs.readFile('./data.txt', 'utf-8', function(err, data){
if(err) throw err;
console.log(data);
});
讀取圖片時,我們是不能直接輸出到控制臺中的,是需要創(chuàng)建一個服務器,然后在瀏覽器上進行查看。其實在上節(jié)中,我們已經(jīng)了解過顯示圖片的過程了。
// server.js
var http = require('http'),
fs = require('fs');
http.createServer(function(request, response){
// 使用二進制方式讀取圖片
fs.readFile('./img/test.png', 'binary', function(err, file){
if( err ) throw err;
// 當前數(shù)據(jù)以image/png方式進行輸出
response.writeHead(200, {"Content-Type": "image/png"});
response.write(file, 'binary');
response.end();
});
}).listen(3000);
console.log('server has started...');
打開瀏覽器:127.0.0.1:3000,就能看到圖片了。
1.2 寫入文件
將字符串寫入到文件文件中,是非常簡單的操作,使用writeFile即可搞定:
var fs = require('fs');
var data = '從一開始,就選擇了做前端開發(fā),因為覺得前端開發(fā)更貼近用戶,能夠傾聽用戶的聲音,更好玩,更有意思,美的更直觀。我們總是在嘗試最新的技術,嘗試更炫的效果,希望更能優(yōu)化用戶的體驗效果!';
fs.writeFile('./test.txt', data, function(err){
if(err) throw err;
console.log('寫入數(shù)據(jù)成功...');
});
writeFile方法,在沒有文件時會創(chuàng)建文件并寫入;若文件存在則內(nèi)容被覆蓋。
1.3 創(chuàng)建或文件重命名
根據(jù)writeFile的特性,可以使用writeFile寫入空字符串的方式創(chuàng)建文件。
同時,fs.open也可以創(chuàng)建文件:
// 打開模式可以使用 w | w+ | a | a+
// 這些模式在打開不存在的文件時,會創(chuàng)建文件
// fd為一個整數(shù),表示打開文件返回的文件描述符,window中又稱文件句柄
fs.open(Date.now()+'.txt', 'a+', function(err, fd){
if(err) throw err;
console.log(fd);
})
在文件系統(tǒng)中,有一個fs.rename的方法,顧名思義,對文件(文件夾)進行重命名。
fs.rename(oldname, newname, callback(err));
特性:
將oldname文件(目錄)移動至newname的路徑下,并重新命名;如果oldname和newname是同一個路徑,則直接進行重命名。
二、文件夾操作
通常對目錄的操作比較簡單一些。
2.1 讀取文件夾中的文件和文件夾列表
使用fs.readdir(path, callback)可以獲取path路徑下的文件和目錄列表,而且只能讀取直接目錄下的文件和文件夾,子目錄里的是獲取不到的。
fs.readdir('./', function(err, files){
if(err) throw err;
console.log( files );
});
輸出結果:
[ 'img', 'msg.txt', 'node_modules', 'package.json', 'server.js', 'test.js', 'tmp' ]
node_modules和tmp是文件夾,剩下的是文件,而且是獲取不到node_modules和tmp里面的數(shù)據(jù)。獲取一個目錄下所有的文件,后面會講解,稍等。
2.2 刪除文件夾
使用fs.rmdir(path, callback)可以刪除文件夾,但只能刪除空文件夾,如果當前路徑不是文件夾或當前文件夾不為空,則刪除失??;刪除的為空文件夾時,可以刪除成功。
fs.rmdir('./tmp', function(err){
if(err){
console.log('刪除文件夾失敗');
throw err;
}else{
console.log('刪除成功');
}
})
如何刪除不為空的目錄,后面會講解,稍等。
2.3 獲取文件或文件夾的信息
fs.stat(path, callback)能夠獲取path路徑的信息,比如創(chuàng)建時間,修改時間,文件大小,當前是否為文件,當前是否為文件夾等信息;如果path路徑不存在,則拋出異常。
fs.stat('./test.js', function(err, stats){
if( err ){
console.log( '路徑錯誤' );
throw err;
}
console.log(stats);
console.log( 'isfile: '+stats.isFile() ); // 是否為文件
console.log( 'isdir: '+stats.isDirectory() ); // 是否為文件夾
});
結果:
{
dev: -29606086,
mode: 33206,
nlink: 1,
uid: 0,
gid: 0,
rdev: 0,
blksize: undefined,
ino: 2251799813687343,
size: 2063, // path路徑為文件夾時,size為0
blocks: undefined,
atime: Thu Jan 12 2017 21:12:36 GMT+0800 (中國標準時間),
mtime: Sat Jan 14 2017 21:57:26 GMT+0800 (中國標準時間),
ctime: Sat Jan 14 2017 21:57:26 GMT+0800 (中國標準時間),
birthtime: Thu Jan 12 2017 21:12:36 GMT+0800 (中國標準時間)
}
isfile: true // 是否為文件
isdir: false // 是否為文件夾
關于這幾個時間屬性的理解,可以參考這篇文章。
stats中的size屬性就是當前文件的大小(單位:字節(jié),除以1024即為kb),stats還有下面方法可供使用:
- stats.isFile()
- stats.isDirectory()
- stats.isBlockDevice()
- stats.isCharacterDevice()
- stats.isSymbolicLink() (only valid with fs.lstat())
- stats.isFIFO()
- stats.isSocket()
fs.stat(path, callback)是異步執(zhí)行的,對應的還有同步執(zhí)行版本:fs.statSync(path) ,這個方法返回的就是fs.stats實例。
三、綜合運用
我們在上面的講解中,還留著兩個功能沒實現(xiàn),這里實現(xiàn)一下它的過程。
3.1 遍歷目錄中所有的文件
我們已經(jīng)知道使用readdir只能獲取當前目錄里的文件和文件夾名稱,為了獲取這個目錄里所有的文件名稱,只能是讀取當前目錄里所有的文件夾里的文件。這里我們使用遞歸的方法,如果當前資源是文件,則進行存儲,是文件夾則進行遞歸進一步檢索,直到把所有的文件夾遍歷完畢。
// 獲取文件夾中所有的文件
function readDirAll(path){
// 獲取字符串的最后一個字符
var getLastCode = function(str){
return str.substr(str.length-1, 1);
}
var result = []; // 存儲獲取到的文件
var stats = fs.statSync(path); // 獲取當前文件的狀態(tài)
if( stats.isFile() ){
result.push(path);
}else if( stats.isDirectory() ){
// 若當前路徑是文件夾,則獲取路徑下所有的信息,并循環(huán)
var files = fs.readdirSync(path);
for(var i=0, len=files.length; i<len; i++){
var item = files[i],
itempath = getLastCode(path)=='/' ? path+item : path+'/'+item; // 拼接路徑
var st = fs.statSync(itempath);
if( st.isFile() ){
result.push(itempath);
}else if( st.isDirectory() ){
// 當前是文件夾,則遞歸檢索,將遞歸獲取到的文件列表與當前result進行拼接
var s = readDirAll( itempath );
result = result.concat( s );
}
}
}
return result;
}
console.log( readDirAll('./') );
使用此程序獲取當前目錄中所有的文件(展示的為部分文件):
[ './bing.doc', './img/1484234634801.png', './img/1484234660592.png', './img/test.png', './inter.js', './msg.txt', './node_modules/formidable/.npmignore', './node_modules/formidable/.travis.yml', './node_modules/formidable/index.js', './node_modules/formidable/lib/file.js', './node_modules/formidable/lib/incoming_form.js', './node_modules/formidable/lib/index.js', ... ]
如果想要輸出一種樹形的結構,就可以對當前的遞歸程序進行改造,比如我想要輸出如下的這種結果,那么,就要分析這種結構的特點:
bing.doc img |---1484234634801.png |---1484234660592.png |---test.png inter.js msg.txt node_modules |---formidable |---.npmignore |---.travis.yml |---index.js |---lib |---file.js |---incoming_form.js |---index.js
可以看出的規(guī)律:
- 第一層級的文件和文件夾前面是沒有空格和字符的;
- 第一級子目錄中的文件或文件夾前面是1組空格和1個字符;
- 第二級子目錄中的文件或文件夾前面是2組空格和1個字符;
- 依次類推…
我們可以再傳遞一個depth來表示當前目錄的層級,然后計算出前面空格的數(shù)量:
// depth為遞歸的深度,可根據(jù)遞歸的深度輸出文件名稱前面的格式
function readDirAll(path, depth){
// 獲取字符串
var getLastCode = function(str){
return str.substr(str.length-1, 1);
}
depth = depth || 0; // 默認為0
var fir_code = '';
// 計算文件名稱前面的字符,4個空格為1組
for(var j=0; j<depth; j++){
fir_code += ' ';
}
depth && (fir_code += '|---');
var stats = fs.statSync(path);
if( stats.isFile() ){
console.log( fir_code+path );
}else if( stats.isDirectory() ){
var files = fs.readdirSync(path);
for(var i=0, len=files.length; i<len; i++){
var item = files[i],
itempath = getLastCode(path)=='/' ? path+item : path+'/'+item,
st = fs.statSync(itempath);
console.log( fir_code+item );
if( st.isDirectory() ){
var s = readDirAll( itempath, depth+1 );
}
}
}
}
console.log( readDirAll('./') );
3.2 刪除目錄
使用fs.rmdir(path)是有局限性的,只能刪除空目錄,如果是個非空目錄,我們可以根據(jù)上面的思路,寫出一個能刪除當前目錄下所有的文件。遞歸,只要找到里面的文件夾就遞歸尋找,直到找到最底層,把最底層的文件刪除,然后再逐級向上刪除文件夾,直到刪除到當前目錄。
// 刪除path下所有的文件和文件夾,包括path自己
function rmDirAll(path){
// 獲取字符串
var getLastCode = function(str){
return str.substr(str.length-1, 1);
}
var stats = fs.statSync(path); // 獲取當前文件的狀態(tài)
if( stats.isFile() ){
fs.unlinkSync(path);
console.log( '刪除成功: '+path );
}else if( stats.isDirectory() ){
// 若當前路徑是文件夾,則獲取路徑下所有的信息,并循環(huán)
var files = fs.readdirSync(path);
for(var i=0, len=files.length; i<len; i++){
var item = files[i],
itempath = getLastCode(path)=='/' ? path+item : path+'/'+item; // 拼接路徑
var st = fs.statSync(itempath);
if( st.isFile() ){
fs.unlinkSync(itempath);
console.log( '刪除成功: '+itempath );
}else if( st.isDirectory() ){
// 當前是文件夾,則遞歸檢索
rmDirAll( itempath );
}
}
// 現(xiàn)在可以刪除文件夾
fs.rmdir(path);
console.log( '刪除成功: '+path );
}
}
rmDirAll('./img');
則刪除時輸出的信息如下,先把內(nèi)部的文件和文件夾刪除干凈,最后刪除 ‘./img':
刪除成功: ./img/1484234634801.png 刪除成功: ./img/1484234660592.png 刪除成功: ./img/gggg/est.txt 刪除成功: ./img/gggg 刪除成功: ./img/test.png 刪除成功: ./img
當然,你也可以試著實現(xiàn)這樣的程序:
- 刪除path內(nèi)部所有的內(nèi)容,同時能保留下path目錄
- 只刪除文件,將所有的空文件夾保留下來
- 將內(nèi)部所有的文件都移動到path的根目錄下,并刪除空文件夾
等等,都可以試著實現(xiàn)一下。
總結
以上就是這篇文章的全部內(nèi)容了,其實文件系統(tǒng)里也有很多的內(nèi)容需要學習,這里只是拋磚引玉,希望通過自己一點的微薄知識,能為大家指點迷津。小編還會繼續(xù)分享關于node入門學習的文章,感興趣的朋友們請繼續(xù)關注腳本之家。
相關文章
基于Node.js的強大爬蟲 能直接發(fā)布抓取的文章哦
基于Node.js的強大爬蟲能直接發(fā)布抓取的文章哦!本爬蟲源碼基于WTFPL協(xié)議,感興趣的小伙伴們可以參考一下2016-01-01
nodejs文件操作模塊FS(File System)常用函數(shù)簡明總結
這篇文章主要介紹了nodejs文件操作模塊FS(File System)常用函數(shù)簡明總結,對FS模塊的大部份異步函數(shù)做了介紹,而且用中文注釋,這下用起來方便了,需要的朋友可以參考下2014-06-06
使用Express+Node.js對mysql進行增改查操作?
這篇文章主要介紹了使用Express+Node.js對mysql進行增改查操作,文章圍繞主題展開詳細的內(nèi)容介紹,具有一定的參考價值,需要的小伙伴可以參考一下2022-08-08
node微信開發(fā)之獲取access_token+自定義菜單
這篇文章主要介紹了node微信開發(fā)之獲取access_token+自定義菜單,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-03-03

