Node.js後端開發 - 基礎篇 #6 讀寫文件(同步,異步)

文章目錄

同步

readFileSync方法

writeFileSync方法

異步

readFile方法

writeFile方法


上一篇文章我們介紹了nodejs的事件,如新建或繼承事件對象,綁定事件對象等,詳見: Node.js後端開發 - 基礎篇 #5 事件 這篇文章我們將介紹nodejs的讀寫文件(同步,異步),那麼怎麼讀寫文件?怎麼把文件的內容讀取出來,然後再把它寫到另一個文件中,並且通過這篇文章我們來簡單理解同步和異步的關係。好了廢話少說,我們來開始編碼!

同步

readFileSync方法

我們可以在app.js裏面寫入以下代碼:

//導入nodejs文件系統的一個庫
var fs = require('fs');

//參數1:文件名路徑,路徑需要加雙引號。
//因爲是當前目錄,所以直接可以寫文件名  
//參數2:編碼格式
var readMe = fs.readFileSync("readMe.txt","utf-8");

我們手動新建一個文件readMe.txt,寫入內容:讀我啊 read me

   

我們來看一看讀取出來的結果:

MacBook-Pro:hello-nodejs luminal$ node app
讀我啊 read me
MacBook-Pro:hello-nodejs luminal$ 

writeFileSync方法

下面我們來看看寫的方法,代碼如下:

var fs = require('fs');

var readMe = fs.readFileSync("readMe.txt","utf-8");

//參數1:要寫入的文件名路徑。沒有的話,它會自動新建
//參數2:要寫入的內容。
fs.writeFileSync("writeMe.txt", readMe);
//fs.writeFileSync("writeMe.txt", "190910馬老師-怒放的生命");

我們來看看輸出結果:

MacBook-Pro:hello-nodejs luminal$ node app
MacBook-Pro:hello-nodejs luminal$ 

因爲是寫入操作,我們沒有日誌輸出,下面我們會發現當前目錄,自動生成了一個 writeMe.txt 的文件

上面是把 readMe 這個對象的內容寫進去了。

當然你也可以自定義內容寫進去 fs.writeFileSync("writeMe.txt", "190910馬老師-怒放的生命");  這個結果就不貼圖了!

異步

readFile方法

上面演示的 readFileSync、writeFileSync都是同步方法,其實sync英文就是同步的意思,那麼有同步就必然有異步,下面我們來看看下面的代碼

var fs = require('fs');

var readMe = fs.readFileSync("readMe.txt","utf-8");

console.log(readMe);

console.log("finished");

我們來看看輸出結果:

MacBook-Pro:hello-nodejs luminal$ node app
讀我啊 read me
finished
MacBook-Pro:hello-nodejs luminal$ 

意思上面四行代碼是同步執行的,從頭到尾一行一行依次執行下來。那如果文件"readMe.txt"非常大,那麼這個讀取的時間就會很長,後面要執行的內容只能排隊等待執行,那麼這種情況顯然不合理!

nodejs執行JavaScript的時候它是單線程的,這裏要注意的是:我並沒有說nodejs是單線程的。這種I/O操作,比如說像數據庫連接是很常見的,也是最耗時的。那麼怎麼來解決這個問題呢?這個時候我們可以用到異步,下面我們修改一下代碼如下:

var fs = require('fs');

var readMe = fs.readFile("readMe.txt","utf-8",function(err, data) {
    console.log(data);
});

// 延遲5秒執行。我們可以用這個模擬感受下,阻塞的狀態!
//也就是說,有如下耗時的同步操作,那就會阻塞整個線程的運行,
//就算是上面異步的方法,也會被阻塞。當遇見這種情況,這時候你寫nodejs,
//都是要用異步的方法來處理
//var waitTill = new Date(new Date().getTime() + 5 * 1000);
//while (waitTill > new Date()) {}

console.log("finished");

我們來看看輸出結果:

MacBook-Pro:hello-nodejs luminal$ node app
finished
讀我啊 read me
MacBook-Pro:hello-nodejs luminal$ 

我們會發現 “finished” 先輸出出來了,那麼怎麼回事呢?

readFile是一個異步方法,修改的代碼執行的是異步事件、異步的I/O操作,nodejs執行JavaScript的時候它是單線程的,上面代碼的語句還是一行一行的執行的。那麼 “finished” 爲什麼會先輸出出來?

其實是這樣的,nodejs它維護了一個事件隊列,上面三行語句中,第一句還是會先執行,執行第二句的時候它就在事件隊列當中註冊了一個事件,告訴這個事件隊列,我將要去讀取一個文件。但是裏面的回調函數並沒有被馬上執行,這個操作是瞬間完成的,完成之後它就會執行主線程的第三條語句 console.log("finished");  

當主線程空閒的時候,它就會去找事件隊列裏面的事件,把它取出來。在此同時發起一個線程去執行事件隊列裏面的事件,在這裏是讀取一個文件,當讀完成功以後,它再告訴主線程我已經執行成功。

因爲I/O操作它有時候是很耗時的,你不能阻塞別的操作,不能讓別的操作一直在等待它的執行,應該是開啓另一個線程就執行這個I/O操作,它執行成功以後再通知主線程去執行它。

writeFile方法

有readFile方法必然會有與之對應的writeFile方法,下面我們來看看代碼:

var fs = require('fs');

// var readMe = fs.readFile("readMe.txt","utf-8",function(err, data) {
//     console.log(data);
// });
var data = "寫寫寫";
fs.writeFile("writeMe.txt", data, function() {
    console.log("寫入完畢!");
});

console.log("finished");

我們來看看輸出結果:

MacBook-Pro:hello-nodejs luminal$ node app
finished
寫入完畢!
MacBook-Pro:hello-nodejs luminal$ 

同樣的,writeFile方法也是異步的方法,所以"finished"先輸出。同時我們會發現,寫入的內容已經寫進去了,如下圖:

 

可參考的api:

https://nodejs.org/dist/latest-v9.x/docs/api/fs.html#fs_fs_write_fd_string_position_encoding_callback

 

 

 

 

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章