fs模組是Node.js官方提供的,用來操作檔案的模組。它提供了一系列的方法和屬性,用來滿足使用者對檔案的操作需求。
使用fs模組操作檔案時,需要先匯入它,程式碼如下:
const fs = require(‘fs’)
(1)同步:程式在涉及到檔案IO時,必須等到檔案IO操作結束後再執行後續的操作。
(2)非同步:程式在涉及到檔案IO時,不等待檔案IO操作結束,繼續執行後續的操作,當檔案IO操作結束後系統會通知程式處理檔案IO的結果。
所有檔案系統操作都具有同步和非同步形式,供開發者選擇。
非同步的形式總是將完成回撥作為其最後一個引數。傳給完成回撥的引數取決於具體方法,但第一個引數始終預留用於異常。如果操作成功完成,則第一個引數是null或undefined。
所謂「回撥」,就是」回頭再調」。回撥函數並不是馬上呼叫,而是需要等到事件觸發了以後再執行。回撥是一個非同步等效的功能,在完成特定任務後回撥函數被呼叫。
用於非同步讀取資料。 - - - - 也叫非阻塞方式讀
語法格式如下:
fs.readFile(path[,options],callback);
path:必選引數,字串,表示檔案的路徑,可以是絕對路徑,也可以是相對路徑。注意,如果是相對路徑,是相對於當前程序所在的路徑(process.cwd()),而不是相對於當前指令碼所在的路徑。
option:可選引數,表示以什麼編碼格式來讀取檔案
callback:必選引數,檔案讀取完成後,通過回撥函數拿到讀取的結果,該函數的第一個引數是發生錯誤時的錯誤物件,第二個引數是代表檔案內容的Buffer範例。
舉例如下:
//匯入fs模組
const fs = require('fs');
//呼叫readFile()方法讀取檔案
fs.readFile('./fs1.txt','utf8',function(err,dataStr){
console.log(err);
console.log('-----');
console.log(dataStr);
});
console.log('非同步讀取檔案')
//err代表列印失敗後的結果,dataStr代表列印成功後的結果
成功時的結果如下:
此時err為null,dataStr為列印出的結果,且我們可以發現,先列印出了「非同步讀取檔案」的結果,這就可以看出fs.readFile()用於非同步讀取資料的特性,在涉及到檔案IO時,它不等待檔案IO操作結束,會繼續執行後續的操作,當檔案IO操作結束後系統會通知程式處理檔案IO的結果。
失敗後的結果如下,此時我們故意寫一個錯誤的檔名。
則err會列印出錯誤物件,dataStr結果為undefined
可以通過err物件是否為null,從而判斷檔案讀取的結果。
//判斷檔案是否讀取成功
//匯入fs模組
const fs = require('fs');
fs.readFile('./fs1.txt','utf8',function (err,result){
if(err){
console.log('讀取失敗:'+err.message)
}else{
console.log('讀取成功')
console.log(result)
}
})
讀取成功時列印結果如下:
讀取失敗時結果如下:
用於同步讀取檔案,返回一個字串。- - - -阻塞方式
語法格式如下:
fs.readFileSync(path[, options]);
readFileSync方法的第一個引數是檔案路徑,第二個引數可以是一個表示設定的物件,也可以是一個表示文字檔案編碼的字串。預設的設定物件是{ encoding: null, flag: ‘r’ },即檔案編碼預設為null,讀取模式預設為r(唯讀)。如果第二個引數不指定編碼(encoding),readFileSync方法返回一個Buffer範例,否則返回的是一個字串。
舉例如下:
//同步讀取檔案
const fs = require('fs');
const str = fs.readFileSync('./fs1.txt','utf8');
console.log(str);
console.log('同步讀取檔案');
結果如下:
可以發現它同步方式處理資料的特性,先等待檔案IO操作結束,返回其結果,再接著往下處理程式。
非同步寫入檔案,如果檔案已經存在將會覆蓋檔案
語法格式:
fs.writeFile(file,data[,option],callback);
file:必選引數,需要指定一個檔案路徑的字串,表示檔案的存放路徑
data:必選引數,表示要寫入的內容
option:可選引數,表示以什麼格式寫入檔案內容,預設值是utf8
callback:必選引數,檔案寫入完成後的回撥函數,回撥函數獲取一個引數err,用於在發生任何寫入錯誤時返回錯誤。
舉例如下:
//匯入fs模組
const fs = require('fs');
//呼叫fs.writeFile()方法,寫入檔案的內容
fs.writeFile('f://ds','我愛北京天安門','utf8',function (err){
if(err){
console.log('寫入失敗:'+err.message)
}else{
console.log('寫入成功')
fs.readFile('./fs1.txt','utf8',function (e,result){
if(e){
return '讀取失敗'+e.message
}else{
console.log(result)
}
})
}
})
在上述程式碼中,我們指定寫入檔案的路徑在F槽裡,可是本電腦是沒有F槽的,所以寫入失敗,列印出錯誤資訊。
//匯入fs模組
const fs = require('fs');
//呼叫fs.writeFile()方法,寫入檔案的內容
fs.writeFile('./fs1.txt','我愛北京天安門','utf8',function (err){
if(err){
console.log('寫入失敗:'+err.message)
}else{
console.log('寫入成功')
console.log('此時的錯誤為:',err)
fs.readFile('./fs1.txt','utf8',function (e,result){
if(e){
console.log('讀取失敗'+e.message)
}else{
console.log(result)
}
})
}
})
這個程式碼路徑正確,按照程式來講,它會列印出寫入成功,然後列印出當成功時err被定義為null,最後讀取出寫入的資訊
可以判斷err物件是否為null,來判斷檔案是否寫入成功。
//匯入fs模組
const fs = require('fs');
//呼叫fs.writeFile()方法,寫入檔案的內容
fs.writeFile('f://fs1.txt','天安門上太陽升',function (err){
if(err){
return console.log('檔案寫入失敗:'+err)
}else{
console.log('檔案寫入成功')
}
});
此時錯誤,err就會被列印出:
我們有一個old.txt檔案,裡面的內容為:
小熊-蜂蜜 小狗-牛奶 小貓-小魚 小柳-陽光
現在想把它整理後放入新檔案new.txt中。整理後的內容為:
小熊:蜂蜜
小狗:牛奶
小貓:小魚
小柳:陽光
步驟如下:
1、匯入fs模組
2、使用readFile()方法,讀取old.txt的內容
3、判斷檔案是否讀取成功
4、讀取成功後,處理內容
5、處理完成後,使用writeFile()方法,將內容寫入到新檔案new.txt中
程式碼如下:
//匯入fs模組
const fs = require('fs');
//使用readFile()方法,讀取old.txt裡的內容
fs.readFile('./old.txt','utf8',function (err,result){
if(err){
console.log('讀取失敗:',err)
}else{
//處理讀取到的資料
//先從空格處分隔字串,使它成為陣列
const newtxt = result.split(' ');
//遍歷陣列,且將每個資料中的-替換為:
const as = [];
for(let k of newtxt){
const b = k.replace('-',':');
as.push(b)
}
//將替換後的陣列轉換為字串,且每一項之間換行
const str = as.join('\n');
//將處理好的檔案通過writeFile()方法寫入new.txt中
fs.writeFile('./new.txt',str,function (err){
if(err){
return console.log('寫入失敗')
}else{
console.log('寫入成功')
}
})
}
在使用fs模組操作檔案時,如果提供的操作路徑是以./或…/開頭的相對路徑時,很容易出現路徑動態拼接錯誤的問題,原因是程式碼在執行的時候,會以執行node命令時所處的目錄,動態拼接出被操作檔案的完整路徑。
解決方案1:在使用fs模組操作檔案時,直接提供完整的路徑,不要提供./或…/開頭的相對路徑,從而防止路徑動態拼接的問題。
注意:在js中,一個\的意思是跳脫,連個\才代表斜線的意思,所以完整路徑要寫為:
C:\\Users\\ace23\\Documents
這種方法的缺點是移植性差,且不利於維護,路徑較長時,一處寫錯會很麻煩
解決方案2:__dirname+’路徑’:__dirname表示當前檔案所處的目錄
如:
const fs = require('fs');
fs.readFile(__dirname+'/fs1.txt','utf8',function (err,result){
if(err){
console.log('讀取失敗:'+err.message)
}else{
console.log('讀取成功')
console.log(result)
}
})
在非同步模式下開啟檔案的語法是:
fs.open(path[, flags[, mode]], callback);
path - 檔名,包括路徑字串。
flags - 標誌要開啟的檔案的方式,預設值: ‘r’。flags引數的常用取值:
–‘r’:以唯讀方式開啟檔案,若檔案不存在則報異常
–‘w’:開啟檔案進行寫入,若檔案不存在則建立檔案
–‘a’:向檔案中追加內容,若檔案不存在則建立檔案
–‘rs’:同步方式開啟檔案
mode - 設定檔案模式,但前提是已建立該檔案。它預設為0666,可讀取和寫入。
callback - 這是回撥函數,有兩個引數(err, fd)。
舉例如下:
//開啟檔案
const fs = require('fs');
fs.open(__dirname+'/fs1.txt',function (err,fd){
fs.readFile('./fs1.txt','utf8',function (err,data){
console.log(data)
})
console.log('開啟檔案成功');
console.log(fd);
});
結果如下:
它產生一個物件,該物件包含了該檔案或目錄的具體資訊。通過該方法,判斷正在處理的是一個檔案,還是一個目錄。語法格式如下:
fs.stat(path[, options], callback);
引數的說明:
path - 檔名,包括路徑字串。
options - bigint 返回的 <fs.Stats> 物件中的數值是否應為 bigint。預設值: false。
callback - 回撥函數得到兩個引數(err, stats) 。其中stats 是 <fs.Stats> 物件,表示檔案的狀態資訊。
我們還可以通過stats的isFile()與isDirectory()方法判斷檔案是否為檔案格式或者資料夾格式。
舉例如下:
//獲取檔案資訊
const fs = require('fs');
fs.stat('./fs1.txt',function (err,stats){
if(err){
return console.log(err);
}
console.log(stats);
console.log(stats.isFile());
});
結果如下:
fs.mkdir(path[, mode], callback);
引數說明:
path - 包括路徑的目錄名。
mode - 要設定的目錄許可權,預設是可讀可寫。
callback - 回撥函數
舉例如下:
//建立目錄
const fs = require('fs');
fs.mkdir('./study',function (err){
if(err){
return console.log(err);
}
console.log('目錄建立成功');
});
fs.rmdir(path, callback);
引數說明:
path - 包括路徑的目錄名。
callback - 回撥函數
舉例如下:
//刪除目錄
const fs = require('fs');
fs.rmdir('./study',function (err){
if(err){
return console.log(err);
}
console.log('目錄刪除成功');
});
fs.readdir(path, callback);
引數說明:
path - 包括路徑的目錄名。
callback - 回撥函數,兩個引數(err, files),其中檔案的檔名的目錄中的陣列排除 ‘.’ 和 ‘…’,'files’是列表,當中放的是當前目錄下的檔案或資料夾名稱。
舉例如下:
//讀取目錄
const fs = require('fs');
fs.readdir('./',function (err,file){
if(err){
return console.log(err);
}
console.log(file);
})
結果如下: