BufferedReader 耗时太长

BufferedReader taking too long

这是为了更快地读取文件而不是写入文件。 我有一个 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

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

您手头有几个问题:

  1. 你抢先解析的太多了

    当您阅读您说 "I get the OOM on decompressedString = reader.readLine();" 后的行时,您遇到的错误已经发生了。

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

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

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

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

    要减少这种情况,请使用适当的库,您可以将上述流之一传递到该库。我在评论中提到了以下内容:Gson, JSON.simple and Jackson.

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

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

    要解决这个问题,您可能需要以下两种方法之一:您想要更少的数据,或者您希望能够集中您的请求。

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

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