在线观看不卡亚洲电影_亚洲妓女99综合网_91青青青亚洲娱乐在线观看_日韩无码高清综合久久

鍍金池/ 教程/ HTML/ API 走馬觀花
文本編碼
小結(jié)
API 走馬觀花
API 走馬觀花
迭代
小結(jié)
運行
回調(diào)
需求
代碼設(shè)計模式
進程介紹
模塊
工程目錄
小結(jié)
小結(jié)
遍歷目錄
小結(jié)
小結(jié)
API 走馬觀花
用途
NPM
小結(jié)
安裝
網(wǎng)絡(luò)操作介紹
二進制模塊
什么是 NodeJS
命令行程序
靈機一點
域(Domain)
應(yīng)用場景
模塊路徑解析規(guī)則
文件拷貝

API 走馬觀花

我們先大致看看 NodeJS 提供了哪些和文件操作有關(guān)的 API。這里并不逐一介紹每個 API 的使用方法,官方文檔已經(jīng)做得很好了。

Buffer(數(shù)據(jù)塊)

官方文檔: http://nodejs.org/api/buffer.html

JS 語言自身只有字符串?dāng)?shù)據(jù)類型,沒有二進制數(shù)據(jù)類型,因此 NodeJS 提供了一個與 String 對等的全局構(gòu)造函數(shù) Buffer 來提供對二進制數(shù)據(jù)的操作。除了可以讀取文件得到 Buffer 的實例外,還能夠直接構(gòu)造,例如:

var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]);

Buffer 與字符串類似,除了可以用.length屬性得到字節(jié)長度外,還可以用[index]方式讀取指定位置的字節(jié),例如:

bin[0]; // => 0x68;

Buffer 與字符串能夠互相轉(zhuǎn)化,例如可以使用指定編碼將二進制數(shù)據(jù)轉(zhuǎn)化為字符串:

var str = bin.toString('utf-8'); // => "hello"

或者反過來,將字符串轉(zhuǎn)換為指定編碼下的二進制數(shù)據(jù):

var bin = new Buffer('hello', 'utf-8'); // => <Buffer 68 65 6c 6c 6f>

Buffer 與字符串有一個重要區(qū)別。字符串是只讀的,并且對字符串的任何修改得到的都是一個新字符串,原字符串保持不變。至于 Buffer,更像是可以做指針操作的 C 語言數(shù)組。例如,可以用[index]方式直接修改某個位置的字節(jié)。

bin[0] = 0x48;

.slice方法也不是返回一個新的 Buffer,而更像是返回了指向原 Buffer 中間的某個位置的指針,如下所示。

[ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]
    ^           ^
    |           |
   bin     bin.slice(2)

因此對.slice方法返回的 Buffer 的修改會作用于原 Buffer,例如:

var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]);
var sub = bin.slice(2);

sub[0] = 0x65;
console.log(bin); // => <Buffer 68 65 65 6c 6f>

也因此,如果想要拷貝一份 Buffer,得首先創(chuàng)建一個新的 Buffer,并通過.copy方法把原 Buffer 中的數(shù)據(jù)復(fù)制過去。這個類似于申請一塊新的內(nèi)存,并把已有內(nèi)存中的數(shù)據(jù)復(fù)制過去。以下是一個例子。

var bin = new Buffer([ 0x68, 0x65, 0x6c, 0x6c, 0x6f ]);
var dup = new Buffer(bin.length);

bin.copy(dup);
dup[0] = 0x48;
console.log(bin); // => <Buffer 68 65 6c 6c 6f>
console.log(dup); // => <Buffer 48 65 65 6c 6f>

總之,Buffer 將 JS 的數(shù)據(jù)處理能力從字符串?dāng)U展到了任意二進制數(shù)據(jù)。

Stream(數(shù)據(jù)流)

官方文檔: http://nodejs.org/api/stream.html

當(dāng)內(nèi)存中無法一次裝下需要處理的數(shù)據(jù)時,或者一邊讀取一邊處理更加高效時,我們就需要用到數(shù)據(jù)流。NodeJS中通過各種 Stream 來提供對數(shù)據(jù)流的操作。

以上邊的大文件拷貝程序為例,我們可以為數(shù)據(jù)來源創(chuàng)建一個只讀數(shù)據(jù)流,示例如下:

var rs = fs.createReadStream(pathname);

rs.on('data', function (chunk) {
    doSomething(chunk);
});

rs.on('end', function () {
    cleanUp();
});

注意: Stream 基于事件機制工作,所有 Stream 的實例都繼承于 NodeJS 提供的 EventEmitter。

上邊的代碼中 data 事件會源源不斷地被觸發(fā),不管 doSomething 函數(shù)是否處理得過來。代碼可以繼續(xù)做如下改造,以解決這個問題。

var rs = fs.createReadStream(src);

rs.on('data', function (chunk) {
    rs.pause();
    doSomething(chunk, function () {
        rs.resume();
    });
});

rs.on('end', function () {
    cleanUp();
});

以上代碼給 doSomething 函數(shù)加上了回調(diào),因此我們可以在處理數(shù)據(jù)前暫停數(shù)據(jù)讀取,并在處理數(shù)據(jù)后繼續(xù)讀取數(shù)據(jù)。

此外,我們也可以為數(shù)據(jù)目標(biāo)創(chuàng)建一個只寫數(shù)據(jù)流,示例如下:

var rs = fs.createReadStream(src);
var ws = fs.createWriteStream(dst);

rs.on('data', function (chunk) {
    ws.write(chunk);
});

rs.on('end', function () {
    ws.end();
});

我們把 doSomething 換成了往只寫數(shù)據(jù)流里寫入數(shù)據(jù)后,以上代碼看起來就像是一個文件拷貝程序了。但是以上代碼存在上邊提到的問題,如果寫入速度跟不上讀取速度的話,只寫數(shù)據(jù)流內(nèi)部的緩存會爆倉。我們可以根據(jù).write方法的返回值來判斷傳入的數(shù)據(jù)是寫入目標(biāo)了,還是臨時放在了緩存了,并根據(jù) drain 事件來判斷什么時候只寫數(shù)據(jù)流已經(jīng)將緩存中的數(shù)據(jù)寫入目標(biāo),可以傳入下一個待寫數(shù)據(jù)了。因此代碼可以改造如下:

var rs = fs.createReadStream(src);
var ws = fs.createWriteStream(dst);

rs.on('data', function (chunk) {
    if (ws.write(chunk) === false) {
        rs.pause();
    }
});

rs.on('end', function () {
    ws.end();
});

ws.on('drain', function () {
    rs.resume();
});

以上代碼實現(xiàn)了數(shù)據(jù)從只讀數(shù)據(jù)流到只寫數(shù)據(jù)流的搬運,并包括了防爆倉控制。因為這種使用場景很多,例如上邊的大文件拷貝程序,NodeJS 直接提供了.pipe方法來做這件事情,其內(nèi)部實現(xiàn)方式與上邊的代碼類似。

File System(文件系統(tǒng))

官方文檔: http://nodejs.org/api/fs.html

NodeJS 通過 fs 內(nèi)置模塊提供對文件的操作。fs 模塊提供的 API 基本上可以分為以下三類:

  • 文件屬性讀寫。

其中常用的有 fs.stat、fs.chmod、fs.chown 等等。

  • 文件內(nèi)容讀寫。

其中常用的有 fs.readFile、fs.readdir、fs.writeFile、fs.mkdir 等等。

  • 底層文件操作。

其中常用的有 fs.open、fs.read、fs.write、fs.close 等等。

NodeJS 最精華的異步 IO 模型在 fs 模塊里有著充分的體現(xiàn),例如上邊提到的這些 API 都通過回調(diào)函數(shù)傳遞結(jié)果。以 fs.readFile 為例:

fs.readFile(pathname, function (err, data) {
    if (err) {
        // Deal with error.
    } else {
        // Deal with data.
    }
});

如上邊代碼所示,基本上所有 fs 模塊 API 的回調(diào)參數(shù)都有兩個。第一個參數(shù)在有錯誤發(fā)生時等于異常對象,第二個參數(shù)始終用于返回 API 方法執(zhí)行結(jié)果。

此外,fs 模塊的所有異步 API 都有對應(yīng)的同步版本,用于無法使用異步操作時,或者同步操作更方便時的情況。同步 API 除了方法名的末尾多了一個 Sync 之外,異常對象與執(zhí)行結(jié)果的傳遞方式也有相應(yīng)變化。同樣以fs.readFileSync 為例:

try {
    var data = fs.readFileSync(pathname);
    // Deal with data.
} catch (err) {
    // Deal with error.
}

fs 模塊提供的 API 很多,這里不一一介紹,需要時請自行查閱官方文檔。

Path(路徑)

官方文檔: http://nodejs.org/api/path.html

操作文件時難免不與文件路徑打交道。NodeJS 提供了 path 內(nèi)置模塊來簡化路徑相關(guān)操作,并提升代碼可讀性。以下分別介紹幾個常用的 API。

path.normalize

將傳入的路徑轉(zhuǎn)換為標(biāo)準(zhǔn)路徑,具體講的話,除了解析路徑中的.與..外,還能去掉多余的斜杠。如果有程序需要使用路徑作為某些數(shù)據(jù)的索引,但又允許用戶隨意輸入路徑時,就需要使用該方法保證路徑的唯一性。以下是一個例子:

  var cache = {};

  function store(key, value) {
      cache[path.normalize(key)] = value;
  }

  store('foo/bar', 1);
  store('foo//baz//../bar', 2);
  console.log(cache);  // => { "foo/bar": 2 }

注意: 標(biāo)準(zhǔn)化之后的路徑里的斜杠在 Windows 系統(tǒng)下是\,而在 Linux 系統(tǒng)下是/。如果想保證任何系統(tǒng)下都使用/作為路徑分隔符的話,需要用.replace(/\\/g, '/')再替換一下標(biāo)準(zhǔn)路徑。

path.join

將傳入的多個路徑拼接為標(biāo)準(zhǔn)路徑。該方法可避免手工拼接路徑字符串的繁瑣,并且能在不同系統(tǒng)下正確使用相應(yīng)的路徑分隔符。以下是一個例子:

  path.join('foo/', 'baz/', '../bar'); // => "foo/bar"

path.extname

當(dāng)我們需要根據(jù)不同文件擴展名做不同操作時,該方法就顯得很好用。以下是一個例子:

  path.extname('foo/bar.js'); // => ".js"

path 模塊提供的其余方法也不多,稍微看一下官方文檔就能全部掌握。

上一篇:什么是 NodeJS下一篇:API 走馬觀花