欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

node.js同步/異步文件讀寫-fs,Stream文件流操作實(shí)例詳解

 更新時(shí)間:2023年06月02日 09:12:06   作者:奔跑的飛牛  
這篇文章主要介紹了node.js同步/異步文件讀寫-fs,Stream文件流操作,結(jié)合實(shí)例形式詳細(xì)分析了node.js針對(duì)文件的同步/異步讀寫與文件流相關(guān)操作技巧,需要的朋友可以參考下

文件讀寫——fs

  • nodejs文檔里api一大堆,該怎么選擇呢?我這里挑選了幾個(gè)常用的出來。

  • 案例說明:當(dāng)前目錄下有index.js和1.txt兩個(gè)文件
    在這里插入圖片描述

  • fs 模塊提供了一些 API,用于以一種類似標(biāo)準(zhǔn) POSIX 函數(shù)的方式與文件系統(tǒng)進(jìn)行交互。

const fs = require('fs');
  • 異步形式的最后一個(gè)參數(shù)都是完成時(shí)回調(diào)函數(shù)。 傳給回調(diào)函數(shù)的參數(shù)取決于具體方法,但回調(diào)函數(shù)的第一個(gè)參數(shù)都會(huì)保留給異常。 如果操作成功完成,則第一個(gè)參數(shù)會(huì)是 null 或 undefined。
const fs = require('fs');
fs.unlink('/tmp/hello', (err) => {
  if (err) throw err;
  console.log('成功刪除 /tmp/hello');
});
  • 當(dāng)使用同步操作時(shí),任何異常都會(huì)被立即拋出,可以使用 try/catch 來處理異常,或讓異常向上冒泡。
const fs = require('fs');
try {
  fs.unlinkSync('/tmp/hello');
  console.log('successfully deleted /tmp/hello');
} catch (err) {
  // handle the error
}

異步的文件讀取

  • 我們先讀取一下這個(gè)文件:
const fs = require("fs");
fs.readFile("./1.txt",(err,data)=>{
    console.log(data);
})

在這里插入圖片描述

我們?cè)趺粗浪_讀取到了呢?一堆16進(jìn)制的buffer.

readFile接收三個(gè)參數(shù),必選參數(shù):路徑,可選參數(shù):編碼,必選參數(shù):回調(diào)函數(shù)。

const fs = require("fs");
fs.readFile("./1.txt","utf-8",(err,data)=>{
    console.log(data);
})

讀取文件

  • 注意兩個(gè)異步不能相干:
const fs = require("fs");
const fn = async () => {
    const data = await new Promise((resovle,reject) => {
        fs.readFile('1.txt','utf-8',(err,data) => {
            if(err) return reject(err)
            resovle(data)      
        })
    })
    console.log(data,111);
}
console.log(1);
console.log(fn(),222);
console.log(2);

在這里插入圖片描述

顯然異步讀取數(shù)據(jù)不能這樣做,人家本身就是異步的,你還拿異步的去取,肯定靠天吃飯啦。

想要準(zhǔn)確的拿數(shù)據(jù),還是得遵守async函數(shù)的規(guī)則,乖乖在它的懷抱下等待。

同步的文件讀取

  • fs.readFileSync(‘路徑’,‘編碼’)
const fs = require("fs");
console.log(1);
const data = fs.readFileSync('1.txt','utf-8')
console.log(data);
console.log(2);

在這里插入圖片描述

很愉快的讀取到數(shù)據(jù),因?yàn)槭峭剑院竺娴拇a必須等待前面讀取文件成功才能繼續(xù)執(zhí)行。如果文件非常大,所以還是乖乖異步吧!

異步的寫文件

fs.writeFile(file, data[, options])

  • fs.writeFile,第一個(gè)參數(shù)為路徑和文件,第二個(gè)參數(shù)為寫入的數(shù)據(jù),第三個(gè)會(huì)回執(zhí)消息,如果沒有錯(cuò)誤會(huì)返回null:

如果你把1.txt刪了或者路徑下沒有這個(gè)文件的話會(huì)自動(dòng)創(chuàng)建文件

const fs = require("fs");
console.log(1);
const data = '寫入測試文字'
fs.writeFile('1.txt',data,res=>{
    console.log(res,11111);
})
console.log(2);

在這里插入圖片描述

但是如果僅是這樣的話,會(huì)把原來的文字覆蓋

同步的寫文件

fs.writeFileSync(file, data[, options])

const fs = require("fs");
console.log(1);
const data = '寫入測試文字'
fs.writeFileSync('1.txt', data, res => {
    console.log(res, 11111);
})
console.log(2);

在這里插入圖片描述

因?yàn)檫@個(gè)寫函數(shù)如果沒有對(duì)應(yīng)文件會(huì)自己新建,所以想報(bào)錯(cuò)還真的很難!暫時(shí)沒有錯(cuò)誤示例!

open,打開文件

fs.open(path, flags[, mode], callback)

四個(gè)參數(shù),mode是默認(rèn)的:

  • path <string> | <Buffer> | <URL>
  • flags <string> |<number>
  • mode <integer> Default: 0o666
  • callback <Function>
    • err<Error>
    • fd <integer>

具體的參數(shù):

flags 可以是:

  • ‘r’ - 以讀取模式打開文件。如果文件不存在則發(fā)生異常。

  • ‘r+’ - 以讀寫模式打開文件。如果文件不存在則發(fā)生異常。

  • ‘rs+’ - 以同步讀寫模式打開文件。命令操作系統(tǒng)繞過本地文件系統(tǒng)緩存。

這對(duì) NFS 掛載模式下打開文件很有用,因?yàn)樗梢宰屇闾^潛在的舊本地緩存。 它對(duì) I/O 的性能有明顯的影響,所以除非需要,否則不要使用此標(biāo)志。

注意,這不會(huì)使 fs.open() 進(jìn)入同步阻塞調(diào)用。 如果那是你想要的,則應(yīng)該使用 fs.openSync()。

  • ‘w’ - 以寫入模式打開文件。文件會(huì)被創(chuàng)建(如果文件不存在)或截?cái)啵ㄈ绻募嬖冢?/p>

  • ‘wx’ - 類似 ‘w’,但如果 path 存在,則失敗。

  • ‘w+’ - 以讀寫模式打開文件。文件會(huì)被創(chuàng)建(如果文件不存在)或截?cái)啵ㄈ绻募嬖冢?/p>

  • ‘wx+’ - 類似 ‘w+’,但如果 path 存在,則失敗。

  • ‘a’ - 以追加模式打開文件。如果文件不存在,則會(huì)被創(chuàng)建。

  • ‘ax’ - 類似于 ‘a’,但如果 path 存在,則失敗。

  • ‘a+’ - 以讀取和追加模式打開文件。如果文件不存在,則會(huì)被創(chuàng)建。

  • ‘ax+’ - 類似于 ‘a+’,但如果 path 存在,則失敗。

mode 可設(shè)置文件模式(權(quán)限和 sticky 位),但只有當(dāng)文件被創(chuàng)建時(shí)才有效。默認(rèn)為 0o666,可讀寫。

  • 該回調(diào)有兩個(gè)參數(shù) (err, fd)。

特有的標(biāo)志 ‘x’(在 open(2) 中的 O_EXCL 標(biāo)志)確保 path 是新創(chuàng)建的。 在 POSIX 操作系統(tǒng)中,path 會(huì)被視為存在,即使是一個(gè)鏈接到一個(gè)不存在的文件的符號(hào)。 該特有的標(biāo)志有可能在網(wǎng)絡(luò)文件系統(tǒng)中無法使用。

flags 也可以是一個(gè)數(shù)字,[open(2)] 文檔中有描述; 常用的常量可從 fs.constants 獲取。 在 Windows 系統(tǒng)中,標(biāo)志會(huì)被轉(zhuǎn)換為與它等同的替代者,例如,O_WRONLY 轉(zhuǎn)換為 FILE_GENERIC_WRITE、或 O_EXCL|O_CREAT 轉(zhuǎn)換為 CREATE_NEW,通過 CreateFileW 接受。

在 Linux 中,當(dāng)文件以追加模式打開時(shí),定位的寫入不起作用。 內(nèi)核會(huì)忽略位置參數(shù),并總是附加數(shù)據(jù)到文件的末尾。

callback[err,fa]

  • 失敗就不說了,讀取成功后,fd將是讀取文件中read方法的第一個(gè)參數(shù),這個(gè)參數(shù)代表指定的文件。

  • 注意:fs.open() 某些標(biāo)志的行為是與平臺(tái)相關(guān)的。 因此,在 macOS 和 Linux 下用 ‘a+’ 標(biāo)志打開一個(gè)目錄(見下面的例子),會(huì)返回一個(gè)錯(cuò)誤。 與此相反,在 Windows 和 FreeBSD,則會(huì)返回一個(gè)文件描述符。

// macOS 與 Linux
fs.open('<directory>', 'a+', (err, fd) => {
  // => [Error: EISDIR: illegal operation on a directory, open <directory>]
});
// Windows 與 FreeBSD
fs.open('<directory>', 'a+', (err, fd) => {
  // => null, <fd>
});

fs.read讀文件,基于open

參數(shù)

  • fd <integer>
  • buffer <Buffer> | <Uint8Array>
  • offset <integer>
  • length <integer>
  • position <integer>
  • callback <Function>
    • err <Error>
    • bytesRead <integer>
    • buffer <Buffer>

參數(shù)的值

  • 從 fd 指定的文件中讀取數(shù)據(jù)。

  • buffer 是數(shù)據(jù)將被寫入到的 buffer。

  • offset 是 buffer 中開始寫入的偏移量。

  • length 是一個(gè)整數(shù),指定要讀取的字節(jié)數(shù)。

position 指定從文件中開始讀取的位置。 如果 position 為 null,則數(shù)據(jù)從當(dāng)前文件讀取位置開始讀取,且文件讀取位置會(huì)被更新。 如果 position 為一個(gè)整數(shù),則文件讀取位置保持不變。

回調(diào)有三個(gè)參數(shù) (err, bytesRead, buffer)。

如果調(diào)用該方法的 util.promisify() 版本,將會(huì)返回一個(gè)包含 bytesRead 和 buffer 屬性的 Promise。

例子:

  • 使用read要和open結(jié)合在一起,通過open返回的fd指定文件拿到要讀取的目標(biāo)!
  • 注意nodejs的buffer已經(jīng)廢棄了很多api!
var fs = require('fs');
fs.open('./1.txt', 'r', function (err, fd) {
    if(err) throw err
    //buf根據(jù)你的需要設(shè)定每次的讀取長度
    var buf = new Buffer.alloc(225);
    //讀取fd文件內(nèi)容到buf緩存區(qū),如果position設(shè)置為null就會(huì)從最開始的地方開始讀
    fs.read(fd, buf, 0, 20, null, function (err, bytesRead, buffer) {
        console.log(buf.slice(0, bytesRead).toString());
        console.log(buf);
    });
});

在這里插入圖片描述

fs.write寫文件,基于open

參數(shù)

  • fd <integer>
  • buffer <Buffer> | <Uint8Array>
  • offset <integer>
  • length <integer>
  • position <integer>
  • callback <Function>
    • err <Error>
    • bytesWritten <integer>
    • buffer <Uint8Array>

參數(shù)的值

  • 寫入 buffer 到 fd 指定的文件。

  • offset 決定 buffer 中被寫入的部分,length 是一個(gè)整數(shù),指定要寫入的字節(jié)數(shù)。

  • position 指向從文件開始寫入數(shù)據(jù)的位置的偏移量。 如果 typeof position !== ‘number’,則數(shù)據(jù)從當(dāng)前位置寫入。詳見 pwrite(2)。

  • 回調(diào)有三個(gè)參數(shù) (err, bytesWritten, buffer),其中 bytesWritten 指定從 buffer 寫入了多少字節(jié)。

  • 如果以 util.promisify() 的形式調(diào)用該方法,則會(huì)返回包含 bytesWritten 和 buffer 屬性的 Promise 的對(duì)象。

  • 注意,多次對(duì)同一文件使用 fs.write 且不等待回調(diào),是不安全的。 對(duì)于這種情況,強(qiáng)烈推薦使用 fs.createWriteStream。

在 Linux 上,當(dāng)文件以追加模式打開時(shí),指定位置的寫入是不起作用的。 內(nèi)核會(huì)忽略位置參數(shù),并總是將數(shù)據(jù)追加到文件的末尾。

例子

var fs = require('fs');
fs.open('./1.txt', 'r+', function (err, fd) {
    if(err) throw err
    fs.write(fd, '文件追加字符測試', 20, 'utf-8', (err, written, buffer)=>{
        console.log(err);
        console.log(buffer);
    })
});

寫入前,別眨眼:
在這里插入圖片描述

寫入后的結(jié)果,寫入位置20,打印err,空,打印buffer,剛才寫入的字符串!

在這里插入圖片描述

  • 提升:位置和數(shù)據(jù)的寫入和讀取就是各位通過邏輯來控制的了!

文件流Stream

  • 想象一下,如果把文件讀取比作向一個(gè)池子里抽水,同步會(huì)阻塞程序,異步會(huì)等待結(jié)果,如果這個(gè)池子特別大怎么辦?有三峽水庫那么大怎么辦?你要等到多久才能喝到抽的水?
  • 因此便會(huì)有了文件流,文件流就好比你一邊抽一邊取,不用等池子滿了再用一樣方便。
  • 因?yàn)榱髟谖募x寫里非常抽象,所以并不能明顯確定,只能勉強(qiáng)通過一些特征表示;
  • fs繼承于Stream;

讀取流例子

const fs = require("fs");
console.log(111111);
const read = fs.createReadStream('1.txt')
read.setEncoding('utf-8')
read.resume();//讓文件流開始'流'動(dòng)起來
read.on('data',data =>{//監(jiān)聽讀取的數(shù)據(jù),如果打印data就是文件的內(nèi)容
    console.log('正在讀');
})
read.on('end', () => { //監(jiān)聽狀態(tài)
    console.log('文件讀取結(jié)束');
})
console.log(222222);

我這里準(zhǔn)備了2萬+行的數(shù)據(jù),監(jiān)聽的data打印了多少次就說明被流監(jiān)聽了多少次,期間就可以使用多少次這個(gè)數(shù)據(jù),用于一些超大型的數(shù)據(jù)讀取還是非常有效的。

在這里插入圖片描述

寫入流

const fs = require("fs");
console.log(111111);
const read = fs.createReadStream('1.txt')
read.setEncoding('utf-8')
read.resume();//讓文件流開始'流'動(dòng)起來
read.on('data',data =>{
    console.log('正在讀');
})
read.on('end', () => { //監(jiān)聽狀態(tài)
    console.log('文件讀取結(jié)束');
})
console.log(222222);
console.log(333333);
const write = fs.createWriteStream('2.txt')
read.pipe(write) //pipe就是那根水管,抽向2.txt
console.log(444444);

如果你自己測試的時(shí)候看著2.txt的行數(shù)在飛漲,會(huì)更加直觀!

在這里插入圖片描述

相關(guān)文章

最新評(píng)論