天天學點node系列-fs文件系統

好的代碼像粥同樣,都是用時間熬出來的。html

概述

文件 I/O 是由簡單封裝的標準 POSIX 函數提供的。 經過 require('fs') 使用該模塊。node

全部文件系統操做都具備同步和異步的形式。緩存

異步的形式老是將完成回調做爲其最後一個參數。 傳給完成回調的參數取決於具體方法,但第一個參數始終預留用於異常。 若是操做成功完成,則第一個參數將爲 null 或 undefined安全

// 異步示例
const fs = require('fs');

fs.unlink('/tmp/hello', (err) => {
  if (err) throw err;
  console.log('已成功刪除 /tmp/hello');
});

使用同步的操做發生的異常會當即拋出,可使用 try/catch 處理,也能夠容許冒泡。app

//同步示例
const fs = require('fs');

try {
  fs.unlinkSync('/tmp/hello');
  console.log('已成功刪除 /tmp/hello');
} catch (err) {
  // 處理錯誤
}

在進程中,建議使用異步版本。 同步的版本將阻塞整個進程,直到它們完成(中止全部鏈接)。可是異步操做不保證執行順序因此,因此在使用時請注意使用對象執行順序。異步

文件系統標誌

flags能夠是:函數

'a' - 打開文件用於追加。若是文件不存在,則建立該文件。
'ax' - 與 'a' 類似,但若是路徑已存在則失敗。
'a+' - 打開文件用於讀取和追加。若是文件不存在,則建立該文件。
'ax+' - 與 'a+' 類似,但若是路徑已存在則失敗。
'as' - 以同步模式打開文件用於追加。若是文件不存在,則建立該文件。
'as+' - 以同步模式打開文件用於讀取和追加。若是文件不存在,則建立該文件。
'r' - 打開文件用於讀取。若是文件不存在,則出現異常。
'r+' - 打開文件用於讀取和寫入。若是文件不存在,則出現異常。
'rs+' - 以同步模式打開文件用於讀取和寫入。指示操做系統繞過本地的文件系統緩存。
'w' - 打開文件用於寫入。若是文件不存在則建立文件,若是文件已存在則截斷文件。
'wx' - 與 'w' 類似,但若是路徑已存在則失敗。
'w+' - 打開文件用於讀取和寫入。若是文件不存在則建立文件,若是文件已存在則截斷文件。
'wx+' - 與 'w+' 類似,但若是路徑已存在則失敗。

底層接口

打開文件

異步打開

// fs.open
path <string> | <Buffer> | <URL>
flags <string> | <number> 參閱支持的文件系統標誌。
mode <integer> 默認值: 0o666(可讀寫)。
callback <Function>
  - err <Error>
  - fd <integer>
var fs = require('fs')
fs.open('1.txt','r',function(err,fs){
    console.log(err)
    console.log(fs)
})

執行結果:ui

$ node 1.js
null
3

注意: 使用'rs+'模式不會使fs.open()進入同步阻塞調用。若是那是你想要的,則應該使用fs.openSync()編碼

同步打開

// fs.openSync
path <string> | <Buffer> | <URL>
flags <string> | <number> 參閱支持的文件系統標誌。
mode <integer> 默認值: 0o666。
返回: <number>
返回表示文件描述符的整數。
var fs = require('fs');
var result = fs.openSync('1.txt','r');
console.log(result);

執行結果:操作系統

$ node 1.js
3

讀取文件

fd <integer> 從 fd 指定的文件中讀取數據。
buffer <Buffer> | <TypedArray> | <DataView> 數據將寫入的緩衝區。
offset <integer> buffer 中開始寫入的偏移量
length <integer> 是一個整數,指定要讀取的字節數
position <integer> 參數指定從文件中開始讀取的位置。 若是 position 爲 null,則從當前文件位置讀取數據,並更新文件位置。 若是 position 是整數,則文件位置將保持不變。
callback <Function>
- err <Error>
- bytesRead <integer>
- buffer <Buffer>
var fs = require('fs');
fs.open('1.txt','r',function(err,fd){
    if(err){
        console.log('文件打開失敗');
    }else{
        var bf = Buffer.alloc(5);
        fs.read(fd,bf,0,3,null,function(err,len,buffer){
            console.log(err);
            console.log(len);
            console.log(buffer);
        })
    }
});

執行結果:

$ node 1.js
null
3
<Buffer 68 65 6c 00 00>

同步讀取

fd <integer>
buffer <Buffer> | <TypedArray> | <DataView>
offset <integer>
length <integer>
position <integer>
返回: <number>
返回 bytesRead 的數量。
var fs = require('fs');
var fd = fs.openSync('1.txt','r');
var bf = Buffer.alloc(5);
var result = fs.readSync(fd,bf,0,3,null);
console.log(result);

執行結果:

$ node 1.js
3

寫入文件

fd <Integer>  文件標識
buffer <String> | <Buffer> 要將buffer中的數據寫入到文件中
offset <Integer> buffer對象中要寫入的數據的起始位置
length <Integer> length是一個整數,指定要寫入的字節數
position <Integer> 指定從文件開始寫入數據的位置的偏移量。 若是 typeof position !== 'number',則數據從當前位置寫入
callback <Function> 回調有三個參數(err, written, buffer),其中written指定從buffer寫入了多少字節

執行結果

$ node 1.js
null
3
<Buffer 74 65 73 74>

[注意]屢次對同一文件使用fs.write且不等待回調,是不安全的。對於這種狀況,強烈推薦使用 fs.createWriteStream  當咱們要對打開的文件進行寫操做的時候,打開文件的模式應該是讀寫模式

同步寫入

fd <integer>
buffer <Buffer> | <TypedArray> | <DataView>
offset <integer>
length <integer>
position <integer>
返回: <number> 寫入的字節數。
var fs = require('fs');
var fd = fs.openSync('1.txt','r+');
var bf = Buffer.alloc(5);
var result = fs.writeSync(fd,bf,0,3,null);
console.log(result);

執行結果:

$ node 1.js
3

關閉文件

fd - 經過 fs.open() 方法返回的文件描述符。
callback - 回調函數,沒有參數。
var fs = require('fs');
fs.open('1.txt','r+',function(err,fd){
    if(err){
        console.log('文件打開失敗');
    }else{
        fs.close(fd, function(err){
            if (err){
                console.log(err);
            } 
            console.log("文件關閉成功");
        });
    }
});
$ node 1.js
文件關閉成功

同步關閉

var fs = require('fs');
var fd = fs.openSync('1.txt','r+');
fs.closeSync(fd);

文件操做

文件讀取

同步讀取

// fs.readFileSync
path <string> | <Buffer> | <URL>
options <string> | <Object>
    encoding <string> 默認值: 'utf8'。
    withFileTypes <boolean> 默認值: false。

返回: <string[]> | <Buffer[]> | <fs.Dirent[]>
var fs = require('fs');
var data;

try{
    data = fs.readFileSync('./1.txt', 'utf8');
    console.log('文件內容: ' + data);
}catch(err){
    console.error('讀取文件出錯: ' + err.message);
}

執行結果爲:

$ node 1.js
文件內容: hello rock

異步讀取

// fs.readFile
path <string> | <Buffer> | <URL>
options <string> | <Object>
    - encoding <string> 默認值: 'utf8'。
    - withFileTypes <boolean> 默認值: false。
callback <Function>
    - err <Error>
    - files <string[]> | <Buffer[]> | <fs.Dirent[]>
var fs = require('fs');

fs.readFile('./1.txt', 'utf8', function(err, data){
    if(err){
        return console.error('讀取文件出錯: ' + err.message);
    }
    console.log('文件內容: ' + data);
});

執行結果也爲:

$ node 1.js
文件內容: hello rock

經過文件流讀取

適合讀取大文件

path <string> | <Buffer> | <URL>
options <string> | <Object>
   - flags <string> 參閱支持的文件系統標誌。默認值: 'r'。
   - encoding <string> 默認值: null。
   - fd <integer> 默認值: null。
   - mode <integer> 默認值: 0o666。
   - autoClose <boolean> 默認值: true。
   - start <integer>
   - end <integer> 默認值: Infinity。
   - highWaterMark <integer> 默認值: 64 * 1024。
返回: <fs.ReadStream> 參閱[可讀流]。
var fs = require('fs');
var readStream = fs.createReadStream('./1.txt', 'utf8');

readStream
    .on('data', function(chunk) {
        console.log('讀取數據: ' + chunk);
    })
    .on('error', function(err){
        console.log('出錯: ' + err.message);
    })
    .on('end', function(){  // 沒有數據了
        console.log('沒有數據了');
    })
    .on('close', function(){  // 已經關閉,不會再有事件拋出
        console.log('已經關閉');
    });

執行結果:

$ node 1.js
讀取數據: hello rock
沒有數據了
已經關閉

文件寫入

異步寫入

// fs.writeFile
file <string> | <Buffer> | <URL> | <integer> 文件名或文件描述符。
data <string> | <Buffer> | <TypedArray> | <DataView>
options <Object> | <string>
  - encoding <string> | <null> 默認值: 'utf8'。
  - mode <integer> 默認值: 0o666。
  - flag <string> 參閱支持的文件系統標誌。默認值: 'w'。
callback <Function>
  - err <Error></Error>
var fs = require('fs');
fs.writeFile('./1.txt', 'hello rock', 'utf8', function(err){
    if(err) throw err;
    console.log('文件寫入成功');
});

執行結果:

$ node 1.js
文件寫入成功

同步寫入

// fs.writeFileSync
file <string> | <Buffer> | <URL> | <integer> 文件名或文件描述符。
data <string> | <Buffer> | <TypedArray> | <DataView>
options <Object> | <string>
  - encoding <string> | <null> 默認值: 'utf8'。
  - mode <integer> 默認值: 0o666。
  - flag <string> 參閱支持的文件系統標誌。默認值: 'w'。
  
返回 undefined。
var fs = require('fs');
try{
    fs.writeFileSync('./1.txt', 'hello rock', 'utf8');
    console.log('文件寫入成功');
}catch(err){
    throw err;
}

執行結果:

$ node 1.js
文件寫入成功

經過文件流寫入

path <string> | <Buffer> | <URL>
options <string> | <Object>
   - flags <string> 參閱支持的文件系統標誌。默認值: 'w'。
   - encoding <string> 默認值: 'utf8'。
   - fd <integer> 默認值: null。
   - mode <integer> 默認值: 0o666。
   - autoClose <boolean> 默認值: true。
   - start <integer>
返回: <fs.WriteStream> 參閱可寫流。
var fs = require('fs');
var writeStream = fs.createWriteStream('./1.txt', 'utf8');
writeStream
    .on('close', function(){ // 已經關閉,不會再有事件拋出
        console.log('已經關閉');
    });
writeStream.write('hello');
writeStream.write('rock');
writeStream.end('');

執行結果:

$ node 1.js
已經關閉

追加文件

file - 文件名或文件描述符。
data - 要寫入文件的數據,能夠是 String(字符串) 或 Buffer(流) 對象。
options - 該參數是一個對象,包含 {encoding, mode, flag}。默認編碼爲 utf8, 模式爲 0666 , flag 爲 'w'
callback - 回調函數,回調函數只包含錯誤信息參數(err),在寫入失敗時返回。
var fs = require('fs');
var filename = '1.txt';
fs.appendFile(filename,' world',function(err){
    console.log(err);
})

執行結果

$ node 1.js
null

同步追加

var fs = require('fs');
var filename = '1.txt';
fs.appendFileSync(filename,' lalala');

刪除文件

path - 文件路徑。
callback - 回調函數,沒有參數。
var fs = require('fs');
var filename = '1.txt';
fs.unlink(filename, function(err) {
   if (err) {
       return console.log('刪除失敗');
   }
   console.log("刪除成功");
});

執行結果:

$ node 1.js
刪除成功

同步刪除

var fs = require('fs');
var filename = '1.txt';
fs.unlink(filename);

重命名

oldPath <String> | <Buffer>
newPath <String> | <Buffer>
callback <Function> 回調只有一個可能的異常參數
var fs = require('fs');
var filename = 'a.txt';
fs.rename(filename,'2.new.txt',function(err){
    console.log(err);
})
$ node 1.js
null

同步重命名

var fs = require('fs');
var filename = '2.new.txt';
var result = fs.renameSync(filename,'a.txt');

文件信息

path <string> | <Buffer> | <URL>
options <Object>
bigint <boolean> 返回的 fs.Stats 對象中的數值是否應爲 bigint 型。默認值: false。
callback <Function>
   - err <Error>
   - stats <fs.Stats>
var fs = require('fs');
var filename = 'a.txt';
fs.stat(filename,function(err,stats){
    console.log(err);
    console.log(stats);
});

執行結果

$ node 1.js
null
Stats {
  dev: 163689085,
  mode: 33206,
  nlink: 1,
  uid: 0,
  gid: 0,
  rdev: 0,
  blksize: undefined,
  ino: 9007199254854088,
  size: 0,
  blocks: undefined,
  atimeMs: 1562684836201.136,
  mtimeMs: 1562684836201.136,
  ctimeMs: 1562684998231.913,
  birthtimeMs: 1562684836201.136,
  atime: 2019-07-09T15:07:16.201Z,
  mtime: 2019-07-09T15:07:16.201Z,
  ctime: 2019-07-09T15:09:58.232Z,
  birthtime: 2019-07-09T15:07:16.201Z }

stats類中的方法有

stats.isFile()  若是是文件返回 true,不然返回 false。
stats.isDirectory() 若是是目錄返回 true,不然返回 false。
stats.isBlockDevice()   若是是塊設備返回 true,不然返回 false。
stats.isCharacterDevice()   若是是字符設備返回 true,不然返回 false。
stats.isSymbolicLink()  若是是軟連接返回 true,不然返回 false。
stats.isFIFO()  若是是FIFO,返回true,不然返回false。FIFO是UNIX中的一種特殊類型的命令管道。
stats.isSocket()    若是是 Socket 返回 true,不然返回 false。
var fs = require('fs');
var filename = 'a.txt';
fs.stat(filename,function(err,stats){
    console.log(stats.isFile());//true
});

監聽

filename <String> | <Buffer>
options <String> | <Object> 參數可選,若是options是一個字符串,則它指定了encoding。不然options應該以一個對象傳入
    persistent <Boolean> 指明若是文件正在被監視,進程是否應該繼續運行。默認爲true
    recursive <Boolean> 指明是否所有子目錄應該被監視,或只是當前目錄。 適用於當一個目錄被指定時,且只在支持的平臺。默認爲false
    encoding <String> 指定用於傳給監聽器的文件名的字符編碼。默認爲'utf8'
listener <Function> 回調函數有兩個參數 (eventType, filename)。 eventType能夠是'rename'或'change',filename是觸發事件的文件的名稱
fs.watch('txt', (eventType, filename) => {
  console.log(`事件類型是: ${eventType}`);
  if (filename) {
    console.log(`提供的文件名: ${filename}`);
  } else {
    console.log('未提供文件名');
  }
});
var fs = require('fs');
var filename = '1.txt';
fs.watch(filename,function(eventType, _filename){
    console.log(eventType);//change
    if(_filename){
        console.log(_filename + '發生了改變');//'1.txt發生了改變'
    }else{
        console.log('...');
    }
    
})

[注意]當一個文件出現或消失在一個目錄裏時,'rename'也會被觸發

相關文章
相關標籤/搜索