最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Java實(shí)現(xiàn)解析JSON大文件JsonReader工具詳解

 更新時間:2023年01月11日 09:59:00   作者:李奈 - Leemon  
這篇文章主要介紹了Java實(shí)現(xiàn)解析JSON大文件的工具JsonReader使用方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧

一,使用背景

之前遇到一個需求,是需要將一個json文件解析存儲到數(shù)據(jù)庫中。一開始測試的時候,json文件的大小都在幾兆以內(nèi),所以直接將json文件轉(zhuǎn)化為字符串,再轉(zhuǎn)化成JSONObject對象進(jìn)行處理時不會出現(xiàn)問題,如下所示:

File file = new File("")
try(FileInputStream fileInputStream = new FileInputStream(file)) {
    int size = fileInputStream.available();
    byte[] buffer = new byte[size];
    fileInputStream.read(buffer);
    String jsonString = new String(buffer, StandardCharsets.UTF_8);
    jsonString.replaceAll("\n", "");
    jsonString.replaceAll("\r", "");
    JSONObject json = JSON.parseObject(jsonString);
}

但是,當(dāng)出現(xiàn)幾十兆文件的時候,這時候就會報出內(nèi)存溢出的錯誤

java.lang.OutOfMemoryError: Java heap space

雖然稍微大一點(diǎn)的文件,可以通過調(diào)整JVM參數(shù)來解決,如下所示

-Xms512m -Xmx2048m

但是這畢竟不是最合理的方法,因?yàn)楫?dāng)文件大到一定程度后,字節(jié)數(shù)組和字符串類型都存在接收不了的情況。因此,只能選擇另外的方式,此時,Google的JsonReader是一個不錯的解決方案。

二,JsonReader的使用

maven依賴如下:

<dependency>
    <groupId>com.google.code.gson</groupId>
    <artifactId>gson</artifactId>
    <version>2.8.6</version>
</dependency>

JsonReader讀取 JSON (RFC 7159) 編碼值作為令牌流。 此流包括文字 值(字符串、數(shù)字、布爾值和空值)以及開始和 對象和數(shù)組的結(jié)束分隔符。 令牌被遍歷 深度優(yōu)先順序,與它們在 JSON 文檔中出現(xiàn)的順序相同。 在 JSON 對象中,名稱/值對由單個標(biāo)記表示。

解析json

創(chuàng)建遞歸下降解析器 JSON ,首先創(chuàng)建 創(chuàng)建一個入口點(diǎn)方法 JsonReader.

每個對象類型和每個數(shù)組類型都需要一個方法。

  • 在 數(shù)組處理 方法中,首先調(diào)用 beginArray()消耗數(shù)組的左括號。 然后創(chuàng)建一個累積值的while循環(huán),在何時終止 hasNext()為false。 最后,通過調(diào)用讀取數(shù)組的右括號 endArray()
  • 在 對象處理 方法中,首先調(diào)用 beginObject()消耗對象的左大括號。 然后創(chuàng)建一個while循環(huán)根據(jù)局部變量的名稱為其賦值。 這個循環(huán)應(yīng)該在什么時候終止 hasNext()為false。 最后,通過調(diào)用讀取對象的右括號 endObject().

當(dāng)遇到嵌套對象或數(shù)組時,委托給對應(yīng)的處理方法。

當(dāng)遇到未知名稱時,嚴(yán)格的解析器應(yīng)該失敗并返回。 但寬松的解析器應(yīng)該調(diào)用 skipValue()遞歸地 跳過值的嵌套標(biāo)記,否則可能會發(fā)生沖突。

如果一個值可能為空,應(yīng)該首先檢查使用 peek(). 空字面量可以使用 nextNull()或者 skipValue().

例如,我之前要解析的json文件格式如下:

{
    "INFO": {
        "NAME": "",
        "Result": "",
        "Config": "",
        ...
    },
    "ATTR": {
        "key01": "val01",
        "key02": "val02",
        ...
    },
    "Parms": [
        {
            "k": "",
            "v": "",
            "p": "",
            "m": "",
            "l": ""
        },
        {
            "k": "",
            "v": "",
            "p": "",
            "m": "",
            "l": ""
        },
        ...
    ],
    "List": ["xxx", "xxxx", ...]
}

那按照J(rèn)sonReader解析的思路,我應(yīng)該先消費(fèi)整體對象的{,再逐個對INFO,ATTR,Parms,List進(jìn)行處理,總而言之,就是

String fileName = "";
FileReader in = new FileReader(fileName);
JsonReader reader = new JsonReader(in);
reader.beginObject();
String rootName = null;
while (reader.hasNext()) {
    rootName = reader.nextName();
    if("INFO".equals(rootName)) {
        reader.beginObject();
        while (reader.hasNext()) {
            System.out.println(reader.nextName() + ":" + reader.nextString())
        }
        reader.endObject();
    }else if("ATTR".equals(rootName)) {
        reader.beginObject();
        while (reader.hasNext()) {
            System.out.println(reader.nextName() + ":" + reader.nextString())
        }
        reader.endObject();
    }else if("Parms".equals(rootName)) {
        reader.beginArray();
        while (reader.hasNext()) {
            reader.beginObject();
            String k = null;
            while (reader.hasNext()) {
                k = reader.nextName();
                switch (k) {
                    case "k":
                        xxx;
                        break;
                    case "v":
                        xxx;
                        break;
                    case "p":
                        xxx;
                        break;
                    case "m":
                        xxx;
                        break;
                    case "l":
                        xxx;
                        break;
                    default:
                        reader.nextString();
                        break;
                }
            }
            reader.endObject();
        }
        reader.endArray();
    }else if("List".equals(rootName)) {
        reader.beginArray();
        while (reader.hasNext()) {
            System.out.println(reader.nextString());
        }
        reader.endArray();
    }else {
        reader.skipValue();
    }
}

常用方法如下所示:

方法名返回值描述
beginArray()void使用JSON流中的下一個令牌,并斷言它是新數(shù)組的開始。
endArray()void使用JSON流中的下一個令牌,并斷言它是當(dāng)前數(shù)組的結(jié)尾。
beginObject()void使用JSON流中的下一個令牌,并斷言它是新對象的開始。
endObject()void使用JSON流中的下一個令牌,并斷言它是當(dāng)前對象的結(jié)尾。
close()void關(guān)閉此 JSON閱讀器 和底層 Reader.
getPath()String返回JSON值中當(dāng)前位置的JsonPath。
hasNext()Boolean如果當(dāng)前數(shù)組或?qū)ο笥衅渌兀瑒t返回true。
isLenient()Boolean如果此解析器在接受的內(nèi)容上是寬松的,則返回true。
setLenient(boolean lenient)void將此解析器配置為在其接受的內(nèi)容上寬松。
nextBoolean()boolean返回boolean下一個令牌的值,并使用它。
nextDouble()double返回double下一個令牌的值,并使用它。
nextInt()int返回int下一個令牌的值,并使用它。
nextLong()long返回long下一個令牌的值,并使用它。
nextName()String返回下一個標(biāo)記,即屬性名,并使用它。
nextNull()void使用JSON流中的下一個令牌,并斷言它是文本null。
nextString()String返回使用下一個標(biāo)記的字符串值。
peek()JsonToken返回下一個令牌的類型,而不使用它
skipValue()void遞歸跳過下一個值。

通過使用JsonReader,現(xiàn)在我解析幾十兆的文件基本沒有問題(上百兆的還沒嘗試過),一個44.5M的JSON文件在4秒就能夠處理完。

到此這篇關(guān)于Java實(shí)現(xiàn)解析JSON大文件JsonReader工具詳解的文章就介紹到這了,更多相關(guān)Java JsonReader內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 使用JPA主鍵@Id,@IdClass,@Embeddable,@EmbeddedId問題

    使用JPA主鍵@Id,@IdClass,@Embeddable,@EmbeddedId問題

    這篇文章主要介紹了使用JPA主鍵@Id,@IdClass,@Embeddable,@EmbeddedId問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • 值得Java開發(fā)者關(guān)注的7款新工具

    值得Java開發(fā)者關(guān)注的7款新工具

    作為老牌語言Java,其生態(tài)圈也出來了一些有關(guān)云服務(wù)、監(jiān)控、文檔分享方面的工具,這篇文章主要介紹了Java開發(fā)者值得關(guān)注的7款新工具,感興趣的小伙伴們可以參考一下
    2016-07-07
  • springboot如何讀取自定義屬性

    springboot如何讀取自定義屬性

    大家好,本篇文章主要講的是springboot如何讀取自定義屬性,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下
    2022-02-02
  • 親身體驗(yàn)Intellij?Idea從卡頓到順暢全過程

    親身體驗(yàn)Intellij?Idea從卡頓到順暢全過程

    這篇文章主要介紹了親身體驗(yàn)Intellij?Idea從卡頓到順暢全過程,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-09-09
  • springboot結(jié)合前端實(shí)現(xiàn)網(wǎng)頁跳轉(zhuǎn)功能實(shí)例

    springboot結(jié)合前端實(shí)現(xiàn)網(wǎng)頁跳轉(zhuǎn)功能實(shí)例

    今天處理Springboot統(tǒng)一異常攔截的時候,遇到了頁面跳轉(zhuǎn)的問題,這篇文章主要給大家介紹了關(guān)于springboot結(jié)合前端實(shí)現(xiàn)網(wǎng)頁跳轉(zhuǎn)功能的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2023-12-12
  • 關(guān)于logback日志級別動態(tài)切換的四種方式

    關(guān)于logback日志級別動態(tài)切換的四種方式

    這篇文章主要介紹了關(guān)于logback日志級別動態(tài)切換的四種方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2023-08-08
  • 教你在Spring Boot微服務(wù)中集成gRPC通訊的方法

    教你在Spring Boot微服務(wù)中集成gRPC通訊的方法

    這篇文章主要介紹了教你在Spring Boot微服務(wù)中集成gRPC通訊的方法,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2021-09-09
  • Springboot常用注解及作用說明

    Springboot常用注解及作用說明

    這篇文章主要介紹了Springboot常用注解及作用說明,Springboot開發(fā)中注解是非常重要的不可或缺的,那么Springboot中有哪些常用的注解呢,今天我們就來看一下這些注解和其作用,需要的朋友可以參考下
    2023-08-08
  • Java中ScheduledExecutorService介紹和使用案例(推薦)

    Java中ScheduledExecutorService介紹和使用案例(推薦)

    ScheduledExecutorService是Java并發(fā)包中的接口,用于安排任務(wù)在給定延遲后運(yùn)行或定期執(zhí)行,它繼承自ExecutorService,具有線程池特性,可復(fù)用線程,提高效率,本文主要介紹java中的ScheduledExecutorService介紹和使用案例,感興趣的朋友一起看看吧
    2024-10-10
  • SpringBoot+MyBatis簡單數(shù)據(jù)訪問應(yīng)用的實(shí)例代碼

    SpringBoot+MyBatis簡單數(shù)據(jù)訪問應(yīng)用的實(shí)例代碼

    這篇文章主要介紹了SpringBoot+MyBatis簡單數(shù)據(jù)訪問應(yīng)用的實(shí)例代碼,需要的朋友可以參考下
    2017-05-05

最新評論

临颍县| 波密县| 田林县| 西和县| 边坝县| 百色市| 松阳县| 哈巴河县| 台中县| 甘洛县| 岳西县| 兰州市| 项城市| 阿合奇县| 克东县| 禄丰县| 镇原县| 宁海县| 平邑县| 六盘水市| 苏尼特左旗| 普兰店市| 阳泉市| 江西省| 武宣县| 彰化市| 青神县| 竹溪县| 庐江县| 宜昌市| 宁海县| 乌鲁木齐市| 霍林郭勒市| 弋阳县| 临沂市| 视频| 右玉县| 八宿县| 松江区| 林甸县| 富平县|