【问题标题】:BufferedReader taking too long [duplicate]BufferedReader 耗时太长 [重复]
【发布时间】:2017-09-01 09:09:22
【问题描述】:

这是为了更快地读取文件而不是写入它。 我有一个 150MB 的文件,里面有一个 JSON 对象。我目前使用以下代码阅读:

String filename ="/tmp/fileToRead";
BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(filename), Charset.forName("UTF-8")));
decompressedString = reader.readLine();
reader.close();
JSONObject obj = new JSONObject(decompressedString);
JSONArray profileData = obj.getJSONObject("profileData").getJSONArray("children");
....

这是一个单行文件,因为它是 JSON,所以我不能拆分它(或者至少我认为是这样)。阅读该文件会给我一个OutOfMemory ErrorTLE。该文件的读取时间超过 7 秒,这会导致 TLE,因为整个代码的执行时间不能超过 7 秒。我在 decompressedString = reader.readLine(); 上收到了 OOM。

有没有办法可以减少使用的内存或完全读取所需的时间?

【问题讨论】:

  • 这是一个读文件而不是写文件的问题。怎么会是写文件的副本呢?
  • @Rjiuk 关于重复,“读取”(BuffereadReader)与“写入”不同。
  • 不要将文件转换为字符串。使用能够直接从文件加载 JSONObject 的 json 库。
  • 另外,如果您想阅读 data,请不要使用 BufferedReader.readLine(),除非您 100% 确定每一行都足够小(小于 4-8 kb)。

标签: java json bufferedreader


【解决方案1】:

你手头有几个问题:

  1. 你抢先解析太多了。

    由于您说“我在 decompressedString = reader.readLine(); 上收到 OOM”,因此您在阅读该行时已经发生了错误。

    你不应该尝试逐行读取数据BufferedReader.readLine() 将一直阻塞,直到您读取字符 \r\n 或序列 \r\n。在处理任何长度的数据时,您永远肯定会得到其中一个字符。此外,您永远无法确定您会得到数据本身之外 的那些字符。所以你的字符串可能太长或格式错误。所以永远不要假装知道格式。解析时必须使用BufferedReader.readLine(),而不是获取数据时使用。

  2. 您没有为您的用例使用合适的库

    阅读您的 JSON 很重要,是的,但是您一次阅读的内容太多了。创建 JSON 时,您可能希望从流(InputStreamReader 或任何 nio 的 Channel/Buffer 之一)构建它。

    目前,您正在从 String 制作 JSON。一个巨大的。因此,我可以放心地假设您将需要两倍于您所需的内存。一次在字符串中,一次在最终对象中。

    要减少这种情况,请使用适当的库,您可以将上述流之一传递给该库。我在我的 cmets 中提到了以下内容:GsonJSON.simpleJackson

  3. 你的文件可能太大了。

    如果您获取数据并且只想获取其中的子集(这里,您想要{"profileData":{"children": <DATA>}} 下的所有内容)。但你可能有太多了。与profileData 处于同一级别的元素有多少?与children 处于同一级别的元素有多少?你知道吗?可能太多了。所有不在profileData.children 之下的东西都是无用的。那占您总数据的百分比是多少? 50%? 90%? 99%?

    要解决这个问题,您可能需要以下两件事之一:您需要更少的数据,或者您希望能够专注于您的请求。

    如果您需要更少的数据,请让您的数据提供商提供更少的数据:只提供您需要的数据。为什么得到更多?这没有道理。告诉他,然后说“我想要的更少”。

    如果您想要集中数据,请使用一个允许您解析和减少数据量的库。您可能希望有一个库可以让您这样说:“解析此 JSON 并仅返回 processingData.children 元素”。 不幸的是,我知道没有图书馆可以做到这一点。如果其他人这样做,请添加评论或答案。显然,如果您自己使用JsonReader并选择性地使用skipValue(),Gson 可以这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-07
    • 2018-02-27
    • 2013-05-28
    • 2014-05-30
    相关资源
    最近更新 更多