JavaScript >> Javascript 文檔 >  >> Node.js

使用 Node.js 讀取文件

幾乎任何編程語言都想做的最常見的事情之一就是打開並讀取文件。對於大多數語言來說,這很簡單,但對於 JavaScript 的老手來說,這似乎有點奇怪。這麼多年來 JavaScript 只在瀏覽器中可用,所以前端開發者可能只熟悉 FileReader API 或類似的。

您可能知道,Node.js 與瀏覽器中的典型 JavaScript 有很大不同。它有自己的一組庫,用於處理操作系統和文件系統任務,例如打開和讀取文件。在本文中,我將向您展示如何使用 Node.js 讀取文件。具體來說,我們將使用 fs 模塊來做到這一點。

有兩種方法可以使用 fs 打開和讀取文件 模塊:

  • 一次加載所有內容(緩衝)
  • 增量加載內容(流式傳輸)

這些方法中的每一個都將在接下來的兩節中進行解釋。

使用 fs.readFile 緩衝內容

這是使用 Node.js 讀取文件的最常用方法,尤其是對於初學者來說,因為它簡單方便。雖然,正如您將在下一節中意識到的那樣,它不一定是最好或最有效的。

下面是一個使用 fs.readFile 的簡單示例:

var fs = require('fs');

fs.readFile('my-file.txt', 'utf8', function(err, data) {
    if (err) throw err;
    console.log(data);
});

data 回調的參數包含文件的全部內容,以 utf8 中的字符串表示 格式。如果您省略 utf8 參數完全,那麼該方法將只返回 Buffer 對像中的原始內容。刪除 utf8 上述代碼中的參數(並假設 my-file.txt 包含字符串“嘿那裡!”),我們會得到這個輸出:

$ node read-file.js
<Buffer 48 65 79 20 74 68 65 72 65 21>

您可能已經註意到 fs.readFile 在回調中返回內容,這意味著此方法異步運行。應該盡可能使用它來避免阻塞主執行線程,但有時您必須同步執行操作,在這種情況下 Node 為您提供了一個 readFileSync 方法。

此方法的工作方式完全相同,只是文件內容直接從函數調用返回,並且執行線程在加載文件時被阻塞。我通常在程序的啟動部分(例如加載配置文件時)或在阻塞主線程不是什麼大問題的命令行應用程序中使用它。

下面是如何使用 Node 同步加載文件:

var fs = require('fs');

try {
    var data = fs.readFileSync('my-file.txt', 'utf8');
    console.log(data);    
} catch(e) {
    console.log('Error:', e.stack);
}

請注意,對於阻塞(同步)調用,我們必須使用 try...catch 處理任何錯誤,不像非阻塞(異步)版本,錯誤只是作為參數傳遞給我們。

除了這些方法返回數據和處理錯誤的方式之外,它們的工作方式非常相似。

使用 fs.createReadStream 流式傳輸內容

第二種打開和讀取文件的方法是使用 fs.createReadStream 方法將其作為 Stream 打開。所有的 Node 流都是 EventEmitter 對象的實例,可以讓你訂閱重要的事件。

可讀的流對像有很多用途,其中一些原因包括:

  • 內存佔用更小 .由於目標文件的數據是以塊的形式加載的,因此在緩衝區中存儲數據所需的內存並不多。
  • 更快的響應時間 .對於時間敏感的應用程序,請求和響應之間的時間至關重要。流縮短了響應時間(尤其是對於大文件),因為它們無需等待加載整個文件即可返回數據。
  • 管道數據 .流抽象允許您使用數據生產者和消費者之間的通用接口通過管道傳遞該數據。這與 Unix 管道概念非常相似。

雖然使用流確實不是很難,但它們可能有點嚇人,並且不像 fs.readFile 那樣直觀 方法。這是文件流的“hello world”:

var fs = require('fs');

var data = '';

var readStream = fs.createReadStream('my-file.txt', 'utf8');

readStream.on('data', function(chunk) {
    data += chunk;
}).on('end', function() {
    console.log(data);
});

這段代碼與第一部分的代碼完全一樣,只是我們必須在將數據打印到控制台之前“收集”數據塊。如果您的文件相當小,那麼您可能只會收到一個塊,但對於較大的文件,如音頻和視頻,您將不得不收集多個塊。在這種情況下,您將開始注意到流文件的真正價值。

免費電子書:Git Essentials

查看我們的 Git 學習實踐指南,其中包含最佳實踐、行業認可的標準以及隨附的備忘單。停止谷歌搜索 Git 命令並真正學習 它!

請注意,我上面展示的示例大部分都違背了使用流的目的,因為我們最終還是將數據收集在緩衝區(變量)中,但至少它讓您了解它們是如何工作的。在處理文件請求的 Express 路由中可以看到顯示文件流優勢的更好示例:

var fs = require('fs');
var path = require('path');
var http = require('http');

var staticBasePath = './static';

var staticServe = function(req, res) {
    var fileLoc = path.resolve(staticBasePath);
    fileLoc = path.join(fileLoc, req.url);
    
        var stream = fs.createReadStream(fileLoc);

        stream.on('error', function(error) {
            res.writeHead(404, 'Not Found');
            res.end();
        });

        stream.pipe(res);
};

var httpServer = http.createServer(staticServe);
httpServer.listen(8080);

我們在這裡所做的就是用 fs.createReadStream 打開文件 並將其傳遞給響應對象 res .我們甚至可以訂閱 error 事件並在它們發生時處理它們。一旦你學會瞭如何正確使用它,這是一種更好的處理文件的方法。上面代碼的更完整的例子和解釋,請查看這篇關於使用 Node 創建靜態文件服務器的文章。

結論

通過這篇文章,你應該已經了解了讀取文件的基礎知識,以及一些使用 Stream 對象的高級加載方法。知道何時使用它們是關鍵,對於內存受限或時間受限的應用程序應仔細考慮。

您首選的文件處理方法是什麼?您過去是如何使用 Streams 的?請在評論中告訴我們!


Tutorial JavaScript 教程
  1. 使用 this.setState 反應原生更新狀態

  2. React Native:使用 React Navigation 的複雜導航

  3. Javascript:.slice 和 .splice 之間的區別

  4. 視頻:使用 HTML、CSS 和 VanillaJS 創建工作列表

  5. 按 ISO 8601 日期對數組進行排序

  6. 使用 React Native 和 Android Studio 創建原生應用

  7. 什麼時候不應該使用 CMS?

  1. 第 10 天:脫離實際行動

  2. JavaScript 中引用類型的介紹和示例

  3. React 中的動畫(多種方式!)

  4. Javascript 驗證日期字符串 |正則表達式、格式、解析方法

  5. 從下拉框中獲取文本

  6. javascript中的錯誤處理

  7. 權威的 Node.js 手冊 – 為初學者學習 Node

  1. 如何在 Homebrew 上發布你的 NodeJS 應用程序

  2. 將材質對話框生命週期移動到 NgRx 效果中

  3. 節點GUI

  4. 適合初學者的 GraphQL