【Node文件系統fs模塊】

環境:Node v8.2.1; Npm v5.3.0; OS Windows10html

一、fs 模塊API

nodejs的文件操做大部分API都提供了同步和異步的兩種方式,下面是異步API結構圖,同步方法在異步方法後面加【Sync】就好了node

1.1 API結構圖

![圖片描述

1.2 文件讀寫模式對應編碼

圖片描述

二、一些例子

下面是部分API的例子,對部分API的一個簡單代碼實現json

2.1 readFile讀取文件

//readFile(filename,[options],callback);

/**
 * filename, 必選參數,文件名
 * [options],可選參數,可指定flag(文件操做選項,如r+ 讀寫;w+ 讀寫,文件不存在則建立)及encoding屬性
 * callback 讀取文件後的回調函數,參數默認第一個err,第二個data 數據
 */

const fs = require("fs");
fs.readFile('./package.json',{flag:"r+",encoding:"utf8"},(err,data)=>{
    if(err)
        throw err;
    console.log(data);
})

2.2 writeFile寫文件

// fs.writeFile(filename,data,[options],callback);
/**
 * filename, 必選參數,文件名
 * data, 寫入的數據,能夠字符或一個Buffer對象
 * [options],flag,mode(權限),encoding
 * callback 讀取文件後的回調函數,參數默認第一個err,第二個data 數據
 */

const fs = require("fs");
const data="hello world";
const bf=Buffer.from(data);
//buffer寫入
fs.writeFile("./test.txt",bf,err=>{
    if(err)
        throw err;
    console.log("寫入成功");
})

//字符寫入
fs.writeFile("./test.txt",data,err=>{
    if(err)
        throw err;
    console.log("寫入成功");
})

2.3 以追加方式寫文件

// fs.appendFile(filename,data,[options],callback);
const fs = require("fs");
const data = " hello world";
const bf = Buffer.from(data);
//buffer
fs.appendFile("./test.txt", bf, err => {
    if (err)
        throw err;
    console.log("追加成功");
})

fs.appendFile("./test.txt", data, err => {
    if (err)
        throw err;
    console.log("追加成功");
})

2.4 open打開文件

打開文件,獲取文件描述數組

// fs.open(filename, flags, [mode], callback);

/**
 * filename, 必選參數,文件名
 * flags, 操做標識,如"r",讀方式打開
 * [mode],權限,如777,表示任何用戶讀寫可執行
 * callback 打開文件後回調函數,參數默認第一個err,第二個fd爲一個整數,表示打開文件返回的文件描述符,window中又稱文件句柄
 */

const fs = require("fs");
fs.open("./test.txt","r",0666,(err,fd)=>{
    if(err)
        throw err;
    console.log(fd);    //3
})

【0666】爲【文件權限碼】,也能夠在【fs.constants】中輸出緩存

2.5 讀文件,讀取打開的文件內容到緩衝區中

//fs.read(fd, buffer, offset, length, position, callback);
/**
 * fd, 使用fs.open打開成功後返回的文件描述符
 * buffer, 一個Buffer對象,v8引擎分配的一段內存
 * offset, 整數,向緩存區中寫入時的初始位置,以字節爲單位
 * length, 整數,讀取文件的長度
 * position, 整數,讀取文件初始位置;文件大小以字節爲單位
 * callback(err, bytesRead, buffer), 讀取執行完成後回調函數,bytesRead實際讀取字節數,被讀取的緩存區對象
 */
const fs = require("fs");
fs.open("./test.txt", "r", (err, fd) => {
    if (err)
        throw err;
    let bf = Buffer.alloc(255);
    fs.read(fd,bf,0,9,0,(err,bytesRead,buffer)=>{
        if(err)
            throw err;
        console.log(bytesRead);
        console.log(buffer.toString());
    })
})

2.6 寫文件,將緩衝區內數據寫入使用fs.open打開的文件

//fs.write(fd, buffer, offset, length, position, callback);

/**
 * fd, 使用fs.open打開成功後返回的文件描述符
 * buffer, 一個Buffer對象,v8引擎分配的一段內存
 * offset, 整數,從緩存區中讀取時的初始位置,以字節爲單位
 * length, 整數,從緩存區中讀取數據的字節數
 * position, 整數,寫入文件初始位置;
 * callback(err, written, buffer), 寫入操做執行完成後回調函數,written實際寫入字節數,buffer被讀取的緩存區對象
 */
const fs = require("fs");
fs.open("./test.txt", "w", (err, fd) => {
    if (err)
        throw err;
    let bf = Buffer.from(" 寫入文件數據的內容");
    fs.write(fd, bf, 0, bf.length, 0, (err, bytesWritten, buffer) => {
        if (err)
            throw err;
        console.log(bytesWritten);
        console.log(`寫入的內容:${buffer.toString()}`);
    })
})

2.7 刷新緩存區

使用fs.write寫入文件時,操做系統是將數據讀到內存,再把數據寫入到文件中,當數據讀完時並不表明數據已經寫完,由於有一部分還可能在內在緩衝區內。
所以可使用fs.fsync方法將內存中數據寫入文件;--刷新內存緩衝區;app

//fs.fsync(fd, [callback])
/**
 * fd, 使用fs.open打開成功後返回的文件描述符
 * [callback(err, written, buffer)], 寫入操做執行完成後回調函數,written實際寫入字節數,buffer被讀取的緩存區對象
 */

const fs = require("fs");
fs.open("./test.txt", "a+", (err, fd) => {
    if (err)
        throw err;
    let bf = Buffer.from(" I love Node");
    fs.write(fd, bf, 0, bf.length, 0, (err, bytesWritten, buffer) => {
        if (err)
            throw err;
       fs.fsync(fd,(err)=>{});
       fs.close(fd,err=>{});
    })
})

2.8 讀取目錄

//使用fs.readdir讀取目錄,重點其回調函數中files對象
//fs.readdir(path, callback);

/**
 * path, 要讀取目錄的完整路徑及目錄名;
 * [callback(err, files)], 讀完目錄回調函數;err錯誤對象,files數組,存放讀取到的目錄中的全部文件名
 */
const fs = require("fs"),
    path = require("path");
fs.readdir(__dirname + "/../11文件系統fs", (err, files) => {
    if (err)
        throw err;
    files.forEach(file => {
        let filePath = path.normalize(__dirname + '/' + file);
        fs.stat(filePath, (err, stats) => {
            if (stats.isFile()) {
                console.log(filePath + ' is: ' + 'file');
            }
            if (stats.isDirectory()) {
                console.log(filePath + ' is: ' + 'dir');
            }
        })
    })
})

三、流操做

3.1 建立讀取流

//fs.createReadStream(path, [options])
/**
 * path 文件路徑
 * [options] flags:指定文件操做,默認'r',讀操做;encoding,指定讀取流編碼;autoClose, 是否讀取完成後自動關閉,默認true;start指定文件開始讀取位置;end指定文件開始讀結束位置
 */
const fs = require("fs");
const rs = fs.createReadStream("./package.json", { flags: "r" });
rs.on("open", fd => console.log('開始讀取文件'));
rs.on('data', data => {
    console.log(data.toString());
})
rs.on('end', function () {
    console.log('讀取文件結束')
});
rs.on('close', function () {
    console.log('文件關閉');
});
rs.on('error', function (err) {
    console.error(err);
});

3.2 建立寫入流

//fs.createWriteStream(path, [options])
/**
 * path 文件路徑
 * [options] flags:指定文件操做,默認'w',;encoding,指定讀取流編碼;start指定寫入文件的位置
 */

/* ws.write(chunk, [encoding], [callback]);
 * chunk,  能夠爲Buffer對象或一個字符串,要寫入的數據
 * [encoding],  編碼
 * [callback],  寫入後回調
 */

/* ws.end([chunk], [encoding], [callback]);
 * [chunk],  要寫入的數據
 * [encoding],  編碼
 * [callback],  寫入後回調
 */
const fs = require("fs");
const ws=fs.createWriteStream("./test.txt",{flags:"w"})
const bf=Buffer.from("I Love Node");
ws.on('open', function () {
    console.log('文件流開啓')
});
ws.on('close', function () {
    console.log('文件流關閉');
});
ws.on('error', function (err) {
    console.error(err);
});  
ws.write(bf,"utf8",(err,buffer)=>{
    console.log('寫入完成')
})
ws.end(' Bye');

3.3 使用流複製文件

流複製文件就是建立一個讀取流和一個寫入流,將讀取流中的流出的數據用寫入流進行寫入異步

//使用流複製文件
const fs = require("fs");

const rs = fs.createReadStream("./package.json");

const ws = fs.createWriteStream("./package1.json");

rs.on("data", data => {
   ws.write(data);
})

ws.on('open', function (fd) {
    console.log('要寫入的數據文件已經打開,文件描述符是: ' + fd);
  });
  
rs.on("end",()=>{
    console.log('文件讀取完成');
    ws.end('完成',()=>{
        console.log("文件寫入完成");
    })
})

關於WriteStream對象的write方法返回一個布爾類型,當緩存區中數據所有寫滿時,返回false;表示緩存區已經寫滿,並將當即輸出到目標對象中。函數

一個例子測試返回值:測試

const fs = require("fs");

var ws = fs.createWriteStream(__dirname + '/test.txt',{flags:"w"});

for (var i = 0; i < 10000; i++) {
  var w_flag = ws.write(i.toString());
  //當緩存區寫滿時,輸出false
  console.log(w_flag);
}

一個例子當緩存區數據所有輸出時,觸發事件ui

const fs = require("fs");

const rs = fs.createReadStream("./ABoy.mp3");

const ws = fs.createWriteStream("./ABoy1.mp3");

rs.on("data", data => {
    let t = ws.write(data);
    if(!t){
        console.log(t);
    }
})

ws.on("drain", () => {
    console.log('系統緩存區數據已經所有輸出。')
})

3.4 pipe管道用於流

上面使用一個讀取流額一個寫入流進行了一次文件的複製,還有另一種方式就是在寫入流和讀取流之間創建一條管道,是讀取流中的數據經過管道源源不斷的流向寫入流,實現文件的複製。

const fs = require("fs");

const rs = fs.createReadStream("./ABoy.mp3");

const ws = fs.createWriteStream("./ABoy1.mp3");

rs.pipe(ws);

rs.on('data', function (data) {
    console.log('數據可讀')
});

rs.on('end', function () {
    console.log('文件讀取完成');
});

ws.on("drain", () => {
    console.log('系統緩存區數據已經所有輸出。')
});

ws.on('open', function (fd) {
    console.log('要寫入的數據文件已經打開,文件描述符是: ' + fd);
});

CSDN 【Node文件系統fs模塊】同步更新

相關文章
相關標籤/搜索