NodeJS提供了的文件操作相關(guān)的API
讓前端覺得如獲神器的不是NodeJS能做網(wǎng)絡(luò)編程,而是NodeJS能夠操作文件,小至文件查找,大至代碼編譯,幾乎沒有一個(gè)前端工具不操作文件,換個(gè)角度講,幾乎也只需要一些數(shù)據(jù)處理邏輯,再加上一些文件操作,就能夠編寫出大多數(shù)前端工具。我們先大致看看NodeJS提供了哪些和文件操作有關(guān)的API。這里并不逐一介紹每個(gè)API的使用方法,官方文檔已經(jīng)做得很好了。
Buffer(數(shù)據(jù)塊)
**官方文檔: **http://nodejs.org/api/buffer.html
JS語言自身只有字符串?dāng)?shù)據(jù)類型,沒有二進(jìn)制數(shù)據(jù)類型,因此NodeJS提供了一個(gè)與String
對等的全局構(gòu)造函數(shù)Buffer
來提供對二進(jìn)制數(shù)據(jù)的操作。除了可以讀取文件得到Buffer
的實(shí)例外,還能夠直接構(gòu)造,例如:
var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]);
Buffer
與字符串類似,除了可以用.length
屬性得到字節(jié)長度外,還可以用[index]
方式讀取指定位置的字節(jié),例如:
bin[0]; // => 0x68;
Buffer
與字符串能夠互相轉(zhuǎn)化,例如可以使用指定編碼將二進(jìn)制數(shù)據(jù)轉(zhuǎn)化為字符串:
var str = bin.toString('utf-8'); // => "hello"
或者反過來,將字符串轉(zhuǎn)換為指定編碼下的二進(jìn)制數(shù)據(jù):
var bin = new Buffer('hello', 'utf-8'); // => <Buffer 68 65 6c 6c 6f>
Buffer
與字符串有一個(gè)重要區(qū)別。字符串是只讀的,并且對字符串的任何修改得到的都是一個(gè)新字符串,原字符串保持不變。至于Buffer
,更像是可以做指針操作的C語言數(shù)組。例如,可以用[index]
方式直接修改某個(gè)位置的字節(jié)。
bin[0] = 0x48;
而.slice
方法也不是返回一個(gè)新的Buffer
,而更像是返回了指向原Buffer
中間的某個(gè)位置的指針,如下所示。
[ 0x68, 0x65, 0x6c, 0x6c, 0x6f ] ^ ^ | | bin bin.slice(2)
因此對.slice
方法返回的Buffer
的修改會(huì)作用于原Buffer
,例如:
var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]); var sub = bin.slice(2); sub[0] = 0x65; console.log(bin); // => <Buffer 68 65 65 6c 6f>
也因此,如果想要拷貝一份Buffer
,得首先創(chuàng)建一個(gè)新的Buffer
,并通過.copy
方法把原Buffer
中的數(shù)據(jù)復(fù)制過去。這個(gè)類似于申請一塊新的內(nèi)存,并把已有內(nèi)存中的數(shù)據(jù)復(fù)制過去。以下是一個(gè)例子。
var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]); var dup = new Buffer(bin.length); bin.copy(dup); dup[0] = 0x48; console.log(bin); // => <Buffer 68 65 6c 6c 6f> console.log(dup); // => <Buffer 48 65 65 6c 6f>
總之,Buffer
將JS的數(shù)據(jù)處理能力從字符串?dāng)U展到了任意二進(jìn)制數(shù)據(jù)。
Stream(數(shù)據(jù)流)
**官方文檔: **http://nodejs.org/api/stream.html
當(dāng)內(nèi)存中無法一次裝下需要處理的數(shù)據(jù)時(shí),或者一邊讀取一邊處理更加高效時(shí),我們就需要用到數(shù)據(jù)流。NodeJS中通過各種Stream
來提供對數(shù)據(jù)流的操作。
以上邊的大文件拷貝程序?yàn)槔覀兛梢詾閿?shù)據(jù)來源創(chuàng)建一個(gè)只讀數(shù)據(jù)流,示例如下:
var rs = fs.createReadStream(pathname); rs.on('data', function (chunk) { doSomething(chunk); }); rs.on('end', function () { cleanUp(); });
豆知識:
Stream
基于事件機(jī)制工作,所有Stream
的實(shí)例都繼承于NodeJS提供的EventEmitter。
上邊的代碼中data
事件會(huì)源源不斷地被觸發(fā),不管doSomething
函數(shù)是否處理得過來。代碼可以繼續(xù)做如下改造,以解決這個(gè)問題。
var rs = fs.createReadStream(src); rs.on('data', function (chunk) { rs.pause(); doSomething(chunk, function () { rs.resume(); }); }); rs.on('end', function () { cleanUp(); });
以上代碼給doSomething
函數(shù)加上了回調(diào),因此我們可以在處理數(shù)據(jù)前暫停數(shù)據(jù)讀取,并在處理數(shù)據(jù)后繼續(xù)讀取數(shù)據(jù)。
此外,我們也可以為數(shù)據(jù)目標(biāo)創(chuàng)建一個(gè)只寫數(shù)據(jù)流,示例如下:
var rs = fs.createReadStream(src); var ws = fs.createWriteStream(dst); rs.on('data', function (chunk) { ws.write(chunk); }); rs.on('end', function () { ws.end(); });
我們把doSomething
換成了往只寫數(shù)據(jù)流里寫入數(shù)據(jù)后,以上代碼看起來就像是一個(gè)文件拷貝程序了。但是以上代碼存在上邊提到的問題,如果寫入速度跟不上讀取速度的話,只寫數(shù)據(jù)流內(nèi)部的緩存會(huì)爆倉。我們可以根據(jù).write
方法的返回值來判斷傳入的數(shù)據(jù)是寫入目標(biāo)了,還是臨時(shí)放在了緩存了,并根據(jù)drain
事件來判斷什么時(shí)候只寫數(shù)據(jù)流已經(jīng)將緩存中的數(shù)據(jù)寫入目標(biāo),可以傳入下一個(gè)待寫數(shù)據(jù)了。因此代碼可以改造如下:
var rs = fs.createReadStream(src); var ws = fs.createWriteStream(dst); rs.on('data', function (chunk) { if (ws.write(chunk) === false) { rs.pause(); } }); rs.on('end', function () { ws.end(); }); ws.on('drain', function () { rs.resume(); });
以上代碼實(shí)現(xiàn)了數(shù)據(jù)從只讀數(shù)據(jù)流到只寫數(shù)據(jù)流的搬運(yùn),并包括了防爆倉控制。因?yàn)檫@種使用場景很多,例如上邊的大文件拷貝程序,NodeJS直接提供了.pipe
方法來做這件事情,其內(nèi)部實(shí)現(xiàn)方式與上邊的代碼類似。
File System(文件系統(tǒng))
**官方文檔: **http://nodejs.org/api/fs.html
NodeJS通過fs
內(nèi)置模塊提供對文件的操作。fs
模塊提供的API基本上可以分為以下三類:
文件屬性讀寫。
其中常用的有
fs.stat
、fs.chmod
、fs.chown
等等。文件內(nèi)容讀寫。
其中常用的有
fs.readFile
、fs.readdir
、fs.writeFile
、fs.mkdir
等等。底層文件操作。
其中常用的有
fs.open
、fs.read
、fs.write
、fs.close
等等。
NodeJS最精華的異步IO模型在fs
模塊里有著充分的體現(xiàn),例如上邊提到的這些API都通過回調(diào)函數(shù)傳遞結(jié)果。以fs.readFile
為例:
fs.readFile(pathname, function (err, data) { if (err) { // Deal with error. } else { // Deal with data. } });
如上邊代碼所示,基本上所有fs
模塊API的回調(diào)參數(shù)都有兩個(gè)。第一個(gè)參數(shù)在有錯(cuò)誤發(fā)生時(shí)等于異常對象,第二個(gè)參數(shù)始終用于返回API方法執(zhí)行結(jié)果。
此外,fs
模塊的所有異步API都有對應(yīng)的同步版本,用于無法使用異步操作時(shí),或者同步操作更方便時(shí)的情況。同步API除了方法名的末尾多了一個(gè)Sync
之外,異常對象與執(zhí)行結(jié)果的傳遞方式也有相應(yīng)變化。同樣以fs.readFileSync
為例:
try { var data = fs.readFileSync(pathname); // Deal with data. } catch (err) { // Deal with error. }
fs
模塊提供的API很多,這里不一一介紹,需要時(shí)請自行查閱官方文檔。
Path(路徑)
**官方文檔: **http://nodejs.org/api/path.html
操作文件時(shí)難免不與文件路徑打交道。NodeJS提供了path
內(nèi)置模塊來簡化路徑相關(guān)操作,并提升代碼可讀性。以下分別介紹幾個(gè)常用的API。
path.normalize
將傳入的路徑轉(zhuǎn)換為標(biāo)準(zhǔn)路徑,具體講的話,除了解析路徑中的
.
與..
外,還能去掉多余的斜杠。如果有程序需要使用路徑作為某些數(shù)據(jù)的索引,但又允許用戶隨意輸入路徑時(shí),就需要使用該方法保證路徑的唯一性。以下是一個(gè)例子:var cache = {}; function store(key, value) { cache[path.normalize(key)] = value; } store('foo/bar', 1); store('foo//baz//../bar', 2); console.log(cache); // => { "foo/bar": 2 }
**坑出沒注意: **標(biāo)準(zhǔn)化之后的路徑里的斜杠在Windows系統(tǒng)下是
\
,而在Linux系統(tǒng)下是/
。如果想保證任何系統(tǒng)下都使用/
作為路徑分隔符的話,需要用.replace(/\\/g, '/')
再替換一下標(biāo)準(zhǔn)路徑。path.join
將傳入的多個(gè)路徑拼接為標(biāo)準(zhǔn)路徑。該方法可避免手工拼接路徑字符串的繁瑣,并且能在不同系統(tǒng)下正確使用相應(yīng)的路徑分隔符。以下是一個(gè)例子:
path.join('foo/', 'baz/', '../bar'); // => "foo/bar"
path.extname
當(dāng)我們需要根據(jù)不同文件擴(kuò)展名做不同操作時(shí),該方法就顯得很好用。以下是一個(gè)例子:
path.extname('foo/bar.js'); // => ".js"
path
模塊提供的其余方法也不多,稍微看一下官方文檔就能全部掌握。
到此這篇關(guān)于NodeJS提供了的文件操作相關(guān)的API的文章就介紹到這了,更多相關(guān)NodeJS文件操作的API內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
node爬取新型冠狀病毒的疫情實(shí)時(shí)動(dòng)態(tài)
這篇文章主要介紹了node爬取新型冠狀病毒的疫情實(shí)時(shí)動(dòng)態(tài),非常不錯(cuò),本文通過實(shí)例代碼給大家講解的非常詳細(xì),需要的朋友可以參考下2020-02-02教你如何用Node實(shí)現(xiàn)API的轉(zhuǎn)發(fā)(某音樂)
這篇文章主要介紹了教你如何用Node實(shí)現(xiàn)API的轉(zhuǎn)發(fā)(某音樂),文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2019-09-09NodeJS學(xué)習(xí)筆記之Connect中間件模塊(一)
這是一個(gè)目錄概要,里面記錄著NodeJS的基礎(chǔ)知識部分,今天這篇文章以及后續(xù)的幾篇,將是一個(gè)進(jìn)階系列,讓我們建立一個(gè)由淺入深的學(xué)習(xí)的過程,2015-01-01npm dose not support Node.js v10.15
這篇文章主要給大家介紹了關(guān)npm dose not support Node.js v10.15.3的解決方法,文中通過圖文介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2023-11-11詳解基于node.js的腳手架工具開發(fā)經(jīng)歷
這篇文章主要介紹了詳解基于node.js的腳手架工具開發(fā)經(jīng)歷,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧2019-01-01nodejs+websocket實(shí)時(shí)聊天系統(tǒng)改進(jìn)版
這篇文章主要介紹了nodejs+websocket實(shí)時(shí)聊天系統(tǒng)的改進(jìn)版,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2017-05-05nodejs實(shí)現(xiàn)文件或文件夾上傳功能的代碼示例
在平常的工作中,經(jīng)常會(huì)遇到需要將本地項(xiàng)目文件同步到遠(yuǎn)端服務(wù)器的情況,所以每次遇到都需要考慮如何將文件上傳到服務(wù)器上,所以本文就給大家介紹一下nodejs實(shí)現(xiàn)文件或文件夾上傳功能,需要的朋友可以參考下2023-08-08修改Nodejs內(nèi)置的npm默認(rèn)配置路徑方法
今天小編就為大家分享一篇修改Nodejs內(nèi)置的npm默認(rèn)配置路徑方法,具有很好的參考價(jià)值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-05-05