2023-09-22|閱讀時間 ‧ 約 11 分鐘

NodeJS 關於 file systems,FS異步同步檔案寫入及讀取操作

NodeJS 學習來到 file systems 操作,在文檔操作上有分為同步跟異步的處理,接下來分階段介紹操作函數

FS 異步寫入

//異步寫入文件 
fs.writeFile(file, data[, options], callback)

參數使用說明如下:

  • file:檔案名稱或檔案描述符。
  • data:要寫入檔案的數據,可以是 String(字串) 或 Buffer(緩衝) 物件。
  • options:此參數是一個對象,包含 {encoding, mode, flag}。 預設編碼為 utf8, 模式為 0666 , flag 為 'w'。
  • callback:回呼函數,回呼函數只包含錯誤訊息參數(err),寫入失敗時回傳。
// 如果文件不存在則直接創建,options 第三個參數為一個可選參數,這邊不寫
// 直接寫回調函數 callback

//導入fs 模塊
const fs = require('fs');

// 導入fs 模塊
const fs = require('fs');

// 寫入文件
fs.writeFile('./123.txt', 'test_test', err => {
if(err){
console.log('寫入失敗');
return;
}
console.log('寫入成功');
})

而在異步處理下會先執行主要的JS線程,而到檔案做寫入時是走IO線程,故為異步操作, 而主線程不等待回調結果,直接往下執行,我們試著在最後增加一個 console.log(1+1); 驗證流程結果

// 如果文件不存在則直接創建,options 第三個參數為一個可選參數,這邊不寫
// 直接寫回調函數 callback

//導入fs 模塊
const fs = require('fs');

// 導入fs 模塊
const fs = require('fs');

// 寫入文件
fs.writeFile('./123.txt', 'test_test', err => {
if(err){
console.log('寫入失敗');
return;
}
console.log('寫入成功');
})

console.log(1+1);

而整個執行,會是如下圖所示,故異步執行效率會較高

FS 同步寫入

//同步寫入文件,差別無回調函數 
fs.writeFileSync(filename, data[, options])

// 同步寫入文件
fs.writeFileSync('./456.text', 'testSync')

參數使用說明如下:

  • file:檔案名稱或檔案描述符。
  • data:要寫入檔案的數據,可以是 String(字串) 或 Buffer(緩衝) 物件。
  • options:此參數是一個對象,包含 {encoding, mode, flag}。 預設編碼為 utf8, 模式為 0666 , flag 為 'w'。

同步寫入的操作,主要是由JS主線程執行然後送到IO線程處理,等待處理完畢後再寫回,才由主線程繼續執行,處理方式無異步效率高。​

FS異步追加寫入

接下來說明當文件寫入一半,需要持續寫入的時候的應用,這時候可以使用file systems下的appendFile去讀取文件並將資料寫入

//异步追加文件内容
fs.appendFile(filename, data[, options], callback)

//異步追加寫入
fs.appendFile('./123.txt', ',這是要追加的內容', err => {
if(err){
console.log('寫入失敗');
return;
}
console.log('追加寫入成功');
});

第一個參數選擇要寫入的檔案名稱,第二個參數帶入要追加的文檔,在包含一個回調函數。

FS同步追加寫入

如果寫入想要要換行,在JS裡面是使用\r\n

//同步追加文件内容
fs.appendFile. fs.appendFileSync(filename, data[, options])

//同步追加寫入
fs.appendFileSync('./456.text', 'testSync追加的內容')

//同步追加寫入
fs.appendFileSync('./456.text', '\r\ntestSync追加的內容')

而如果使用上面原本的fs.writeFile想作為追加寫入的行為,可以在option參數加上 {flag: 'a'},即可實現追加寫入


//異步寫入文件仿照追加寫入
fs.writeFile('./123.txt', 'yoyo', {flag: 'a'}, err => {
if(err){
console.log('寫入失敗');
return;
}
console.log('寫入成功');
});

而這裡的flag: 'a'主要是append的意思,即是打開文件進行寫入的操作,這表示當文件已存在,則新的數據將會追加到文件的末尾,而不是覆蓋原有內容。

而option其他參數可以參考以下

FS流式寫入

這邊講解FS流式寫入使用createWriteStream方法。

fs.createWriteStream(path[, options])

createWriteStream 與 writeFile 差異在於writeFile一次性處理完畢後就斷開連接通道,而createWriteStream會持續連接通道直到關閉,而適合持續寫入的場景,writeFile則適合寫入較少的場景。

// 導入fs 模塊 
const fs = require('fs');

// 1.創建寫入流
const ws = fs.createWriteStream('./789.txt');

// 2. write
ws.write('123');
ws.write('456');
ws.write('789');
ws.write('101112');

// 3. 關閉通道
ws.close(); //這個步驟為可選,因為正常在寫入完成後,資源將會被釋放出來而斷開


FS文件讀取

在 file systems文件讀取也分為異步fs.readFile()及同步fs.readFileSync()

//異步讀取文件​
fs.readFile(filename[, options], callback)

//同步讀取文件​
fs.readFileSync(filename[, options])

而fs.readFile 的callback function 有兩個參數

// 導入fs 模塊 
const fs = require('fs');

// 異步讀取
fs.readFile('./123.txt', (err, data) => {
if(err){ console.log('寫入失敗');
return;
}

console.log(data); }); // err 作為錯誤訊息的回調,data 為接收讀取資料的結果

這邊可以看到讀取到的內容是一個 buffer ,而需要知道實際內容可以透過toString()方法將buffer轉成字串。


// 導入fs 模塊
const fs = require('fs'); // 異步讀取
fs.readFile('./123.txt', (err, data) => {
if(err){ console.log('寫入失敗');
return;
}

console.log(data.toString());

而如果是使用同步讀取的方式,只要帶入文件路徑即可

// 同步讀取 
let data = fs.readFileSync('./123.txt');
console.log(data.toString());

FS流式讀取

流式讀取主要是切割多個chunk 一次讀取一個chunk執行,在實際應用上讀取大型文件時可以提高讀取效率。

fs.createReadStream(path[, options])

在讀取文件後回調函數的執行,是當讀取一塊數據就會執行一次回調,這邊創建讀取一個mp4的檔案,綁定一個data事件並console.log(chunk)看看結果。

// 導入fs 模塊 
const fs = require('fs');

// 創建讀取流對象
const rs = fs.createReadStream('./video.mp4');

// 綁定data事件
rs.on('data', chunk => { console.log(chunk) })

而我們可以透過使用lenght來知道獲取buffer的長度,可以打印出來後看到每一次切割為65536 => 64KB => 表示一次讀取一個64KB的 chunk

// 導入fs 模塊 
const fs = require('fs');

// 創建讀取流對象
const rs = fs.createReadStream('./video.mp4');

// 綁定data事件
rs.on('data', chunk => { console.log(chunk.length)

而使用上在讀取流中執行,通常會觸發一個end事件,而這個事件是可選的,可加可不加

// 導入fs 模塊
const fs = require('fs');

// 創建讀取流對象
const rs = fs.createReadStream('./video.mp4');

// 綁定data事件
rs.on('data', chunk => {
console.log(chunk.length)
})

// end
rs.on('end', () => {
console.log('讀取完成');
})





小結:以上就是關於 file systems 對於檔案的寫入操作,下一篇就要說明關於file systems的文件讀取方法應用~





分享至
成為作者繼續創作的動力吧!
© 2024 vocus All rights reserved.