在上一篇文章中,我们学习了如何解析过大的XML文件并将其转换为RxJava流。 这次让我们看一个大的JSON文件。 我们的示例将基于微小的colors.json,其中包含将近150种这种格式的记录:

{"aliceblue": [240, 248, 255, 1],"antiquewhite": [250, 235, 215, 1],"aqua": [0, 255, 255, 1],"aquamarine": [127, 255, 212, 1],"azure": [240, 255, 255, 1],//...

鲜为人知的事实: 天蓝色也是一种颜色,而Python是蛇。 但是回到RxJava。 这个文件很小,但是我们将用它来学习一些原理。 如果遵循它们,您将能够加载和连续处理任意大,甚至无限长的JSON文件。 首先,标准的“ Jackson ”方式类似于JAXB:将整个文件加载到内存中并将其映射到Java bean。 但是,如果文件的大小为兆字节或千兆字节(由于某种原因,您发现JSON是存储千兆字节数据的最佳格式……),则此技术将无法使用。 幸运的是,杰克逊提供了类似于StAX的流模式。

使用Jackson逐个令牌加载JSON文件

使用JSON并将其转换为对象集合的标准ObjectMapper没错。 但是为了避免将所有内容加载到内存中,我们必须使用下面的ObjectMapper使用的较低级API。 让我们再次看一下JSON示例:

{"aliceblue": [240, 248, 255, 1],"antiquewhite": [250, 235, 215, 1],//...

从磁盘和内存的角度来看,这是一个单维字节流,我们可以在逻辑上将其聚合为JSON令牌:

START_OBJECT        '{'
FIELD_NAME          'aliceblue'
START_ARRAY         '['
VALUE_NUMBER_INT    '240'
VALUE_NUMBER_INT    '248'
VALUE_NUMBER_INT    '255'
VALUE_NUMBER_INT    '1'
END_ARRAY           ']'
FIELD_NAME          'antiquewhite'
START_ARRAY         '['
VALUE_NUMBER_INT    '250'
VALUE_NUMBER_INT    '235'
VALUE_NUMBER_INT    '215'
VALUE_NUMBER_INT    '1'
END_ARRAY           ']'
...

你明白了。 如果您熟悉编译器理论,这是编译期间的第一步。 编译器将源代码从字符转换为令牌。
但是,如果您了解编译器理论,则可能不是为了生存而解析JSON。 无论如何! Jackson库以这种方式工作,我们可以在没有透明对象映射的情况下使用它:

import com.fasterxml.jackson.core.JsonFactory;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.core.JsonToken;JsonParser parser = new JsonFactory().createParser(new File("colors.json"));
parser.nextToken(); // JsonToken.START_OBJECT;
while (parser.nextToken() != JsonToken.END_OBJECT) {final String name = parser.getCurrentName();parser.nextToken(); // JsonToken.START_ARRAY;parser.nextValue();final int red = parser.getIntValue();parser.nextValue();final int green = parser.getIntValue();parser.nextValue();final int blue = parser.getIntValue();parser.nextValue();parser.getIntValue();System.out.println(name + ": " + red + ", " + green + ", " + blue);parser.nextToken(); // JsonToken.END_ARRAY;
}
parser.close();

…或者如果您摆脱了一些重复,并使代码更易于阅读:

import lombok.Value;JsonParser parser = new JsonFactory().createParser(new File("colors.json"));
parser.nextToken(); // JsonToken.START_OBJECT;
while (parser.nextToken() != JsonToken.END_OBJECT) {System.out.println(readColour(parser));
}
parser.close();//...private Colour readColour(JsonParser parser) throws IOException {final String name = parser.getCurrentName();parser.nextToken(); // JsonToken.START_ARRAY;final Colour colour = new Colour(name,readInt(parser),readInt(parser),readInt(parser),readInt(parser));parser.nextToken(); // JsonToken.END_ARRAY;return colour;
}private int readInt(JsonParser parser) throws IOException {parser.nextValue();return parser.getIntValue();
}@Value
class Colour {private final String name;private final int red;private final int green;private final int blue;private final int alpha;
}

它与RxJava有什么关系? 您可能会猜测–我们可以按需逐块读取此JSON文件。 这使背压机制可以无缝工作:

final Flowable colours = Flowable.generate(() -> parser(new File("colors.json")),this::pullOrComplete,JsonParser::close);

让我解释一下这三个lambda表达式在做什么。 第一个设置JsonParser我们的可变状态,将用于产生( 拉动 )更多项目:

private JsonParser parser(File file) throws IOException {final JsonParser parser = new JsonFactory().createParser(file);parser.nextToken(); // JsonToken.START_OBJECT;return parser;
}

没有什么花哨。 第二个lambda表达式至关重要。 每当订户希望接收更多项目时,都会调用它。 如果它要求100个项目,则此lambda表达式将被调用100次:

private void pullOrComplete(JsonParser parser, Emitter<Colour> emitter) throws IOException {if (parser.nextToken() != JsonToken.END_OBJECT) {final Colour colour = readColour(parser);emitter.onNext(colour);} else {emitter.onComplete();}
}

当然,如果到达END_OBJECT (关闭整个JSON文件),则表明流已结束。 最后一个lambda表达式仅允许清除状态,例如通过关闭JsonParser和基础File 。 现在想象一下这个JSON文件的大小为数百GB。 有了Flowable<Colour>我们可以以任意速度安全地使用它,而不会冒内存过载的风险。

翻译自: https://www.javacodegeeks.com/2017/09/streaming-large-json-file-jackson-rxjava-faq.html

用杰克逊流式传输大型JSON文件– RxJava常见问题解答相关推荐

  1. 迈克尔 杰克逊mv_用杰克逊流式传输大型JSON文件– RxJava常见问题解答

    迈克尔 杰克逊mv 在上一篇文章中,我们学习了如何解析过大的XML文件并将其转换为RxJava流. 这次让我们看一个大的JSON文件. 我们的示例将基于微小的colors.json,其中包含将近150 ...

  2. Java 异步响应servlet_java – 使用jersey流式传输大型响应,异步

    我想允许客户端(包括非常慢的客户端)从JAX-RS(泽西岛)Web服务下载大文件,我被卡住了.似乎JAX-RS中的异步胖子不支持这一点. >如果必须等待资源在服务器端可用,AsyncRespon ...

  3. mysql 结果集 超大_使用MySQL流式传输大型结果集

    我正在开发一个使用大型MySQL表的spring应用程序.加载大表时,我得到一个OutOfMemoryException,因为驱动程序试图将整个表加载到应用程序内存中. 我尝试使用 statement ...

  4. OKHTTP 实现流式传输上传文件

    1. 引入okhttp依赖 implementation 'com.squareup.okhttp3:okhttp:4.10.0' 2. 编写工具类 object HttpUtils {private ...

  5. grpc 流式传输_编写下载服务器。 第一部分:始终流式传输,永远不要完全保留在内存中...

    grpc 流式传输 下载各种文件(文本或二进制文件)是每个企业应用程序的生死攸关的事情. PDF文档,附件,媒体,可执行文件,CSV,超大文件等.几乎每个应用程序迟早都必须提供某种形式的下载. 下载是 ...

  6. Java:将JDBC ResultSet作为JSON流式传输

    这篇文章展示了如何将java.sql.ResultSet转换为JSON并将其流回调用方. 如果要将大型数据集从JDBC数据源以JSON格式发送到Web应用程序,此功能很有用. 流式传输使您可以一点一点 ...

  7. 读取csv文件 java_Java:逐步读取/流式传输CSV文件

    读取csv文件 java 我一直在做一些涉及读取CSV文件的工作,而我一直在使用OpenCSV ,而我的最初方法是逐行读取文件,解析内容并将其保存到地图列表中. 当文件的内容适合内存时,此方法有效,但 ...

  8. Java:逐步读取/流式传输CSV文件

    我一直在做一些涉及读取CSV文件的工作,而我一直在使用OpenCSV ,而我的最初方法是逐行读取文件,解析内容并将其保存到地图列表中. 当文件的内容适合内存时,此方法有效,但对于较大的文件来说是个问题 ...

  9. 从MongoDB GridFS流式传输文件

    不久前,我在Twitter上发布了自己的最新作品,即从MongoDB GridFS传输文件进行下载(而不是将整个文件存储到内存中然后提供服务),这是我取得的一个小胜利. 我答应就此事写博客,但不幸的是 ...

最新文章

  1. 最小割 ---- 二分图最大独立集(集合冲突模型) ---- 骑士共存 方格取数(网络流24题)
  2. 省委书记表态:以“倾省之力”,支持中国科大建国际校区!
  3. html5可以用flash,HTML5网页可以直接看视频,不用flash吗,另外WP7为何不支持flash。。。HTML5网页...
  4. ssas 面试题_多维模型的SSAS面试问题
  5. [翻译] RAReorderableLayout
  6. 跟对人,走对路,做对事!
  7. java 删除文件或文件夹的7种方法(io基础)
  8. wireshark 安装失败报错,缺少kb2999226补丁的解决方案
  9. HTML的字体10种酷炫效果
  10. EDEM创建用于模拟颗粒工厂的多边形后,选中多边形视图中不显示红色多边形
  11. python上海房价数据分析_Python数据分析告诉你为何上海的二手房你都买不起
  12. 使用Vue指令实现下拉菜单效果
  13. 怎么合并mp3音频文件?
  14. java 时间计算差值
  15. 面部识别软件可以帮助女性找到看起来像他们的卵子捐赠者
  16. 无盘服务器接几根网线,设置无线路由器需要几根网线_安装路由器需要几根网线?-192路由网...
  17. r5 5600x性能 r5 5600x有核显吗
  18. [基础]-requests模块使用详解
  19. 很久未使用计算机会怎样,很久没用,电脑为什么不能启动?
  20. Vivado 2019.1安装包下载

热门文章

  1. eclipse搭建多module项目的坑
  2. 使用org.apache.commons.io.FileUtils,IOUtils工具类操作文件
  3. 聊聊并发(八)——Fork/Join框架介绍
  4. Oracle入门(十二B)之表创建
  5. Spring 思维导图,让 Spring 不再难懂(cache篇)
  6. Layui hint: Table element property lay-data configuration item has a syntax error解决方式
  7. Hibernate中使用Criteria查询及注解——( EmpCondition)
  8. 拦截器中/* vs /** ------SpringMVC
  9. 方舟非主机服务器无限距离,方舟非专业服务器距离限制怎么解除 | 手游网游页游攻略大全...
  10. (转) SpringBoot接入两套kafka集群