中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Node.js中流式處理大JSON文件

發布時間:2021-06-22 17:28:56 來源:億速云 閱讀:247 作者:chen 欄目:web開發

這篇文章主要講解了“怎么在Node.js中流式處理大JSON文件”,文中的講解內容簡單清晰,易于學習與理解,下面請大家跟著小編的思路慢慢深入,一起來研究和學習“怎么在Node.js中流式處理大JSON文件”吧!

場景描述

問題一:假設現在有一個場景,有一個大的 JSON  文件,需要讀取每一條數據經過處理之后輸出到一個文件或生成報表數據,怎么能夠流式的每次讀取一條記錄?

[   {"id": 1},   {"id": 2},   ... ]

問題二:同樣一個大的 JSON 文件,我只讀取其中的某一塊數據,想只取 list 這個對象數組怎么辦?

{  "list": [],   "otherList": [] }

在 Node.js 中我們可以基于以下幾種方式讀取數據,也是通常首先能夠想到的:

  • fs.readFile():這個是一次性讀取數據到內存,數據量大了都占用到內存也不是好辦法,很容易造成內存溢出。

  • fs.createReadStream():創建一個可讀流,能解決避免大量數據占用內存的問題,這是一個系統提供的基礎 API  讀取到的是一個個的數據塊,因為我們的 JSON 對象是結構化的,也不能直接解決上面提的兩個問題。

  • 還有一個 require() 也可以加載 JSON 文件,但是稍微熟悉點 Node.js CommonJS 規范的應該知道 require  加載之后是會緩存的,會一直占用在服務的內存里。

了解下什么是 SAX

SAX 是 Simple API for XML 的簡稱,目前沒有一個標準的 SAX 參考標準,最早是在 Java  編程語言里被實現和流行開的,以 Java 對 SAX  的實現后來也被認為是一種規范。其它語言的實現也是遵循著該規則,盡管每門語言實現都有區別,但是這里有一個重要的概念 “事件驅動” 是相同的。

實現了 SAX 的解析器擁有事件驅動那樣的 API,像 Stream 的方式來工作,邊讀取邊解析,用戶可以定義回調函數獲取數據,無論 XML  內容多大,內存占用始終都會很小。

這對我們本節有什么幫助?我們讀取解析一個大 JSON 文件的時候,也不能把所有數據都加載到內存里,我們也需要一個類似 SAX  這樣的工具幫助我們實現。

基于 SAX 的流式 JSON 解析器

這是一個流式 JSON 解析器 https://github1s.com/creationix/jsonparse  周下載量在 600 多萬,但是這個源碼看起來很難梳理。如果是學習,推薦一個基于 SAX 的更簡單版本

https://gist.github.com/creationix/1821394 感興趣的可以看看。

JSON 是有自己的標準的,有規定的數據類型、格式。這個 JSON  解析器也是在解析到特定的格式或類型后觸發相應的事件,我們在使用時也要注冊相應的回調函數。

下面示例,創建一個可讀流對象,在流的 data 事件里注冊 SaxParser 實例對象的 parse 方法,也就是將讀取到的原始數據(默認是  Buffer 類型)傳遞到 parse() 函數做解析,當解析到數據之后觸發相應事件。

對應的 Node.js 代碼如下:

const SaxParser = require('./jsonparse').SaxParser; const p = new SaxParser({   onNull: function () { console.log("onNull") },   onBoolean: function (value) { console.log("onBoolean", value) },   onNumber: function (value) { console.log("onNumber", value) },   onString: function (value) { console.log("onString", value) },   onStartObject: function () { console.log("onStartObject") },   onColon: function () { console.log("onColon") },   onComma: function () { console.log("onComma") },   onEndObject: function () { console.log("onEndObject") },   onStartArray: function () { console.log("onEndObject") },   onEndArray: function () { console.log("onEndArray") } });  const stream = require('fs').createReadStream("./example.json"); const pparse = p.parse.bind(p); stream.on('data', parse);

怎么去解析一個 JSON 文件的數據已經解決了,但是如果直接這樣使用還是需要在做一些處理工作的。

JSONStream 處理大文件

這里推薦一個 NPM 模塊 JSONStream,在它的實現中就是依賴的 jsonparse  這個模塊來解析原始的數據,在這基礎之上做了一些處理,根據一些匹配模式返回用戶想要的數據,簡單易用。

下面我們用 JSONStream 解決上面提到的兩個問題。

問題一:

假設現在有一個場景,有一個大的 JSON  文件,需要讀取每一條數據經過處理之后輸出到一個文件或生成報表數據,怎么能夠流式的每次讀取一條記錄?

因為測試,所以我將 highWaterMark 這個值調整了下,現在我們的數據是下面這樣的。

[   { "id": 1 },   { "id": 2 } ]

重點是 JSONStream 的 parse 方法,我們傳入了一個 '.',這個 data 事件也是該模塊自己處理過的,每次會為我們返回一個對象:

  • 第一次返回 { id: 1 }

  • 第二次返回 { id: 2 }

const fs = require('fs'); const JSONStream = require('JSONStream');  (async () => {   const readable = fs.createReadStream('./list.json', {     encoding: 'utf8',     highWaterMark: 10   })   const parser = JSONStream.parse('.');   readable.pipe(parser);   parser.on('data', console.log); })()
問題二:

同樣一個大的 JSON 文件,我只讀取其中的某一塊數據,想只取 list 這個數組對象怎么辦?

解決第二個問題,現在我們的 JSON 文件是下面這樣的。

{   "list": [     { "name": "1" },     { "name": "2" }   ],   "other": [     { "key": "val" }   ] }

與第一個解決方案不同的是改變了 parse('list.*') 方法,現在只會返回 list 數組,other 是不會返回的,其實在 list  讀取完成之后這個工作就結束了。

  • 第一次返回 { name: '1' }

  • 第二次返回 { name: '2' }

(async () => {   const readable = fs.createReadStream('./list.json', {     encoding: 'utf8',     highWaterMark: 10   })   const parser = JSONStream.parse('list.*');   readable.pipe(parser);   parser.on('data', console.log); })();
總結

當我們遇到類似的大文件需要處理時,盡可能避免將所有的數據存放于內存操作,應用服務的內存都是有限制的,這也不是最好的處理方式。

文中主要介紹如何流式處理類似的大文件,更重要的是掌握編程中的一些思想,例如 SAX 一個核心點就是實現了 “事件驅動” 的設計模式,同時結合 Stream  做到邊讀取邊解析。

處理問題的方式是多樣的,還可以在生成 JSON 文件時做拆分,將一個大文件拆分為不同的小文件。

學會尋找答案,NPM 生態發展的還是不錯的,基本上你能遇到的問題大多已有一些解決方案了,例如本次問題,不知道如何使用 Stream 來讀取一個 JSON  文件時,可以在 NPM 上搜索關鍵詞嘗試著找下。

怎么在Node.js中流式處理大JSON文件

感謝各位的閱讀,以上就是“怎么在Node.js中流式處理大JSON文件”的內容了,經過本文的學習后,相信大家對怎么在Node.js中流式處理大JSON文件這一問題有了更深刻的體會,具體使用情況還需要大家實踐驗證。這里是億速云,小編將為大家推送更多相關知識點的文章,歡迎關注!

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

嘉峪关市| 如皋市| 大宁县| 汝城县| 株洲县| 新源县| 松滋市| 保定市| 樟树市| 肥西县| 峡江县| 巴彦淖尔市| 荃湾区| 石河子市| 湾仔区| 台南市| 鹤庆县| 大英县| 太白县| 竹山县| 朝阳县| 潞西市| 金溪县| 榆林市| 玉门市| 兴化市| 临沧市| 阿城市| 怀来县| 南京市| 竹溪县| 宣恩县| 高台县| 阜平县| 台安县| 泌阳县| 潼关县| 丰镇市| 余姚市| 庆元县| 唐山市|