Node.js的文件系統(tǒng)
JavaScript的是沒有操作文件的能力宜猜,但是Node.js是可以做到的块请。
Node.js提供了操作文件的接口亡呵,但是接口有太多抬探。主要使用一些常用的接口。
文件系統(tǒng)模塊是一個封裝了標準的 POSIX 文件 I/O 操作的集合衣吠。通過 require('fs') 使用這個模塊茶敏。所有的方法都有同步和異步兩種模式。
Node.js的文件系統(tǒng)API
1.讀取文件
Node.js提供了兩種方式讀取文件缚俏,一個是異步的方式讀取文件惊搏,一個是同步的方式讀取文件。
var fs = require("fs");
// 我們來定義一個函數(shù)忧换,用來讀取文件
function readFile (fileUrl) {
console.log("--開始讀取--");
fs.readfile(fileUrl,function(err,data){
if(err){
console.log("--讀取失敗--")
}
console.log("讀取到的數(shù)據(jù)是:"+data.toString());
})
}
readFile("./src/test.txt");
// 執(zhí)行函數(shù)恬惯,就能讀取到文件的信息
// 上邊是異步讀取數(shù)據(jù),同步讀取數(shù)據(jù)是
// 同步讀取函數(shù)
function readFileSync(fileUrl) {
console.log("----開始同步讀取----");
var data = fs.readFileSync(fileUrl);
console.log("同步讀取的數(shù)據(jù)是" + data.toString());
console.log("----讀取結(jié)束----")
}
readFileSync("./src/test.txt");
// 推薦使用異步讀取數(shù)據(jù)亚茬,速度快酪耳,性能好,不會阻塞刹缝;
2.寫入文件
// fs.writeFile(filename,data,[options],callback);
/**
* filename, 必選參數(shù)碗暗,文件名
* data, 寫入的數(shù)據(jù),可以字符或一個Buffer對象
* [options],flag,mode(權限),encoding梢夯,都是選填
* callback 讀取文件后的回調(diào)函數(shù)言疗,參數(shù)默認err
*/
// 寫文件
var w_data = "我是寫入的內(nèi)容";
fs.writeFile("./src/test.txt",w_data,function (err) {
if (err) {
console.error(err);
}
console.log("寫入成功")
})
// 有一點不得不提,就是如果你寫入的文件是已經(jīng)存在的文件颂砸,那么之前的內(nèi)容會被覆蓋掉噪奄。
// 下邊的方法就是把你寫入內(nèi)容追加到原來的文件中;
3.追加內(nèi)容
// fs.appendFile(filename,data,[options],callback)
/**
* filename,必填參數(shù)沾凄,文件名
* data梗醇,追加的內(nèi)容
* options知允,選填撒蟀,flag,mode温鸽。保屯。。
* callback涤垫,默認參數(shù)err
*/
// 追加內(nèi)容
var appendData = "我是被追加的內(nèi)容";
fs.appendFile("./src/test.txt",appendData,function (err) {
if (err) {
console.error(err);
}
console.log("追加內(nèi)容成功姑尺!")
})
4.關于打開文件,讀取文件蝠猬, 截取文件切蟋,寫入文件,關閉文件榆芦,
4.1 先來看看打開文件
fs.open(filename,flag,[mode],callback)
參數(shù)說明
/**
* filename,必填參數(shù)
* flags柄粹,必填參數(shù)喘鸟,詳細參考這些參數(shù)設置
* mode,選填驻右,設置權限
* callback什黑,默認參數(shù)第一個err,第二個fd堪夭,這個fd是個啥玩意愕把,解釋如下
* fd為一個整數(shù),表示打開文件返回的文件描述符森爽,window中又稱文件句柄
*/
/*Flag 描述
r 以讀取模式打開文件恨豁。如果文件不存在拋出異常。
r+ 以讀寫模式打開文件爬迟。如果文件不存在拋出異常圣絮。
rs 以同步的方式讀取文件。
rs+ 以同步的方式讀取和寫入文件雕旨。
w 以寫入模式打開文件扮匠,如果文件不存在則創(chuàng)建。
wx 類似 'w'凡涩,但是如果文件路徑存在棒搜,則文件寫入失敗。
w+ 以讀寫模式打開文件活箕,如果文件不存在則創(chuàng)建力麸。
wx+ 類似 'w+', 但是如果文件路徑存在育韩,則文件讀寫失敗克蚂。
a 以追加模式打開文件,如果文件不存在則創(chuàng)建筋讨。
ax 類似 'a'埃叭, 但是如果文件路徑存在,則文件追加失敗悉罕。
a+ 以讀取追加模式打開文件赤屋,如果文件不存在則創(chuàng)建。
ax+ 類似 'a+'壁袄, 但是如果文件路徑存在类早,則文件讀取追加失敗。
*/
一個實例寫法:
fs.open("./src/test.txt","r+",function (err,fd) {
if (err) {
console.error(err);
}
console.log(fd)// fd 是一個windows系統(tǒng)的句柄嗜逻,類似于給文件一個標識涩僻,后邊會用到
// 還記得定時器么,瀏覽器就會給每個定時器一個id,我們每次清除定時器逆日,就是清除對應id的定時器
console.log("文件被打開了")
// 文件被打開恼琼,但是,是在內(nèi)存中打開的屏富,你根本看不到的晴竞,不用在這做糾結(jié)。
})
4.2 讀取文件
文件被打開了狠半,那么我肯定是要讀取的呀噩死!
file.read(filename,buffer,offset,length,position,callback)
/**
* fd, 使用fs.open打開成功后返回的文件描述符
* buffer, 一個Buffer對象,v8引擎分配的一段內(nèi)存
* offset, 整數(shù)神年,向緩存區(qū)中寫入時的初始位置已维,以字節(jié)為單位
* length, 整數(shù),讀取文件的長度
* position, 整數(shù)已日,讀取文件初始位置垛耳;文件大小以字節(jié)為單位
* callback(err, bytesRead, buffer), 讀取執(zhí)行完成后回調(diào)函數(shù),bytesRead實際讀取字節(jié)數(shù)飘千,被讀取的緩存區(qū)對象
*/
讀取文件的實例:
fs.open("./src/test.txt","r+",function (err,fd) {
if (err) {
console.error(err)
}
console.log("文件被打開了")
console.log("準備讀取文件");
var buffer = new Buffer(1024);
// fd 在read的時候用到了堂鲜,其實類似于一個文件的標識
fs.read(fd,buffer,0,buffer.length,0,function (err,bytesRead,buffer) {
if (err) {
console.error(err)
}
console.log(bytesRead+" 字節(jié)被讀")
if (bytesRead>0) {
console.log("讀取的內(nèi)容"+buffer.toString())
}
})
})
4.3 截取文件
fs.// fs.ftruncate(fd,len,callback)
/**
* fd,打開文件時候的fd
* len,要截取的長度
* callback,回調(diào)函數(shù),沒有參數(shù)
*/
截取文件實例护奈,截取完成后關閉文件:
// 這是一套缔莲,打開文件,截取文件霉旗,讀取文件痴奏,最后關閉文件
fs.open("./src/test.txt","r+",function (err,fd) {
if (err) {
console.log(err)
}
console.log("打開文件成功!")
console.log("準備截取文件");
// 也就是說厌秒,文件被截取之后读拆,能讀到的就是被截取的部分
fs.ftruncate(fd,10,function (err) {
if (err) {
console.log(err)
}
console.log("截取文件成功!");
console.log("開始讀取文件");
fs.read(fd,buffer,0,buffer.length,0,function (err,bytesRead) {
if (err) {
console.error(err)
}
console.log(bytesRead+" 字節(jié)被讀取");
if (bytesRead>0) {
console.log(buffer.slice(0,bytesRead).toString())
}
// 關閉文件
fs.close(fd,function (err) {
if (err) {
console.log(err)
}
console.log("文件關閉")
})
})
})
})
文件被截取之后鸵闪,能讀到就是被截取的部分
4.4 關閉文件
具體用法檐晕,如上例所示
fs.close(fd,callback)
/**
* fd,打開文件時候的fd
* callback,回調(diào)函數(shù),參數(shù)err
*/
4.5 寫入文件
// fs.write(fd,buffer,offset,length,position,callback);
/**
* fd, 使用fs.open打開成功后返回的文件描述符
* buffer, 一個Buffer對象岛马,v8引擎分配的一段內(nèi)存
* offset, 整數(shù)棉姐,從緩存區(qū)中讀取時的初始位置屠列,以字節(jié)為單位
* length, 整數(shù)啦逆,從緩存區(qū)中讀取數(shù)據(jù)的字節(jié)數(shù)
* position, 整數(shù),寫入文件初始位置笛洛;
* callback(err, written, buffer), 寫入操作執(zhí)行完成后回調(diào)函數(shù)夏志,written實際寫入字節(jié)數(shù),buffer被讀取的緩存區(qū)對象
*/
寫入文件實例:
fs.open("./src/test.txt","r+",function (err,fd) {
if (err) {
console.error(err)
}
console.log("文件被打開了");
console.log("準備寫入文件");
var buf = new Buffer("寫入的內(nèi)容");
fs.write(fd,buf,0,buf.length,0,function (err,written,buffer) {
if (err) {
console.error(err)
}
// 寫入文件的字符數(shù),一個中文沟蔑,utf8編碼三個字節(jié)
console.log(written);
// 我們會發(fā)現(xiàn)之前的text.txt文件被改寫了
console.log(buffer.toString())
})
fs.close(fd,function (err) {
if (err) {
console.error(err)
}
console.log("文件被關閉了")
})
})
5.獲取文件信息
// fs.stat(filename,callback)
/**
* filename湿诊,必填參數(shù),文件路徑和文件名稱
* callback瘦材,第一個參數(shù)err厅须,第二個stats,返回一個文件相關的信息
*/
獲取文件信息實例:
fs.stat(__dirname+"/test.txt",function (err,stats) {
if (err) {
console.error(err)
}
console.log(stats)
})
6.創(chuàng)建文件夾
// fs.mkdir(filname,callback)
/**
* filename,必填參數(shù)
* callback食棕,只有一個err參數(shù)
*/
fs.mkdir(__dirname+"/test/",function (err) {
if (err) {
console.error(err)
}
console.log("文件夾創(chuàng)建成功朗和!")
})
7.讀取文件夾
// fs.readdir(filename,{options},callback)
/**
* filename,必填參數(shù)
* options,選填參數(shù)
* callback簿晓,第一個參數(shù)err眶拉,第二個參數(shù)files,返回的是一個文件的數(shù)組
*/
讀取文件夾實例:
// 我們在剛才創(chuàng)建的test文件夾下憔儿,添加兩個文件看看忆植,一個是index.js,index.html
fs.readdir(__dirname+"/test",function (err,files) {
if (err) {
console.error(err)
}
console.log("讀取文件夾成功!")
console.log(files)
files.forEach(function (value,index) {
console.log(value+"---"+index)
})
})
8.刪除文件
// fs.unlink(filename,callback)
/**
* filename,必填參數(shù)
* callback谒臼,參數(shù)err
*/
刪除文件的實例:
// 在新建的test文件夾內(nèi)在新建一個index.txt文件朝刊,然后我們再把它刪掉
fs.unlink(__dirname+"/test/index.txt",function (err) {
if (err) {
console.error(err)
}
console.log("刪除成功!")
})
9.刪除文件夾
fs.rmdir(fliename,callback);
/**
* filename,必填參數(shù)
* callback蜈缤,參數(shù)err
*/
// 清空文件夾坞古,同步操作
function cleanDir(filename) {
// 采用同步的方式讀目標文件夾,獲取files對象
var files = fs.readdirSync(filename);
// 遍歷files對象劫樟,直接forEach了
files.forEach((item) => {
var stats = fs.statSync(filename+"/"+item);
// 判斷當前是文件還是文件夾
if (stats.isDirectory()) {
// 如果是文件夾就重復調(diào)用方法
cleanDir(filename+"/"+item)
}else{
// 如果不是文件夾痪枫,那就是文件,直接刪除
fs.unlinkSync(filename+"/"+item);
console.log("刪除文件"+filename+"/"+item+"成功")
}
})
}
// 刪除每個空文件夾叠艳,同步操作
function deleteDir(filename) {
// 同步方式讀取文件夾奶陈,得到files
var files = fs.readdirSync(filename);
// 判斷files下是否存在別的文件夾,也就是判斷l(xiāng)ength
if (files.length>0) {
var tempFile = 0;
files.forEach((item) => {
tempFile++;
deleteDir(filename+"/"+item);
})
// 如果把子文件夾都刪除了附较,那么母文件夾的filename和上述的不同吃粒,需要單獨列出來,
// 做一步判斷拒课,然后刪除母文件夾
if (tempFile==files.length) {
fs.rmdirSync(filename)
console.log("刪除文件夾"+filename+"成功")
}
}else{
fs.rmdirSync(filename)
console.log("刪除文件夾"+filename+"成功")
}
}
cleanDir(__dirname + "/test");
deleteDir(__dirname + "/test");
基本上Node.js的文件系統(tǒng)最常用的api,大體都接觸了一遍徐勃。