如何处理大字符串和有限的内存

Posted

技术标签:

【中文标题】如何处理大字符串和有限的内存【英文标题】:How to deal with big strings and limited memory 【发布时间】:2011-01-10 01:00:17 【问题描述】:

我有一个从中读取数据的文件。 该文件中的所有文本都存储在一个字符串变量(一个非常大的变量)中。 然后在我的应用程序的另一部分,我想逐步浏览这个字符串并提取有用的信息(解析字符串)。

与此同时,我的内存已满,OutOfMemory 异常使我无法进行进一步处理。 我认为在从文件中读取输入流时直接处理数据会更好。但出于组织目的,我想将字符串传递给我的应用程序的另一部分。

如何防止内存溢出?

【问题讨论】:

你不能用其中一个阅读器(例如 BufferedReader)逐位解析文件吗? 【参考方案1】:

您应该使用BufferedInputReader 而不是将这些全部存储到一个大字符串中。

如果您要解析的内容恰好在同一行,那么StringTokenizer 会很好地工作,否则您必须设计一种方法从文件中读取您想要的内容以解析出语句,然后将 StringTokenizer 应用于每个语句。

【讨论】:

+1。 Anthony:一般的想法是你通过 CURSORS(就像在 DB 中一样)。它们可以是文本情况下的阅读器,字节情况下的流,项目序列情况下的迭代器,或其他任何东西。您可以将一种类型转换为另一种类型(将序列中的每个项目,例如,将文件中的一行转换为某个域对象)但是应用程序的一个区域提供给另一个区域的是光标,因此它是一个句柄来使用一次输入一个步骤,而无需了解读取文件或您在中间实现的任何转换。 您提供的BufferedInputReaderStringTokenizer的链接不可用。【参考方案2】:

如果您可以稍微放宽您的要求,您可以实现由您的文件支持的java.lang.CharSequence。

支持 CharSequence many places in the JDK (A String is a CharSequence) 。因此,这是基于 Reader 实现的一个很好的替代方案。

【讨论】:

【参考方案3】:

其他人建议一次读取和处理文件的某些部分。如果可能的话,其中一种方法会更好。

但是,如果这是不可能的,并且您可以按照您的指示最初将String 加载到内存中,但稍后解析该字符串会产生问题,您可以使用子字符串。在 Java 中,子字符串映射到原始 char 数组的顶部,并且只占用基本 Object 的内存,然后是 start 和 length int 指针。

因此,当您找到要单独保留的字符串的一部分时,请使用以下内容:

String piece = largeString.substring(foundStart, foundEnd);

如果您改为使用这个或内部执行此操作的代码,那么内存使用将急剧增加:

new String(largeString.substring(foundStart, foundEnd));

请注意,出于这个原因,您必须小心使用String.substring()。您可以有一个非常大的字符串,从中取出一个子字符串,然后丢弃对原始字符串的引用。问题是子字符串仍然引用原始的大 char 数组。在子字符串也被删除之前,GC 不会释放它。在这种情况下,实际使用new String(...) 来确保GC 丢弃未使用的大数组很有用(这是您应该使用new String(...) 的少数情况之一)。

如果您希望有很多小字符串并且这些字符串可能具有相同的值,但来自外部源(如文件),另一种技术是在创建新字符串后使用.intern()

注意:这确实取决于 String 的实现,您确实不必了解这一点,但实际上对于大型应用程序,有时您确实必须依赖这些知识。请注意,Java 的未来版本可能会改变这一点(尽管不太可能)。

【讨论】:

【参考方案4】:

您必须检查处理大数据的算法。您必须逐块处理此数据,或者使用随机文件访问而不将数据存储在内存中。例如,您可以像 @Zombies 所说的那样使用 StringTokenizer 或 StreamTokenizer。 您可以看到 parser-lexer 技术:当 parser 解析某个表达式时,它要求 lexer 读取下一个 lexem(tokens),但不会一次读取整个输入流。

【讨论】:

以上是关于如何处理大字符串和有限的内存的主要内容,如果未能解决你的问题,请参考以下文章

如何处理大 JSON 响应

如何处理大数据库?

如何处理大维度表

如何处理大黄蜂表现不佳? [关闭]

HTTP 文件上传如何处理大文件?

chaiscript 如何处理大对象?