【问题标题】:How to deal with big strings and limited memory如何处理大字符串和有限的内存
【发布时间】:2023-03-31 05:08:02
【问题描述】:

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

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

如何防止内存溢出?

【问题讨论】:

  • 你不能用其中一个阅读器(例如 BufferedReader)逐位解析文件吗?

标签: java string memory out-of-memory


【解决方案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),但不会一次读取整个输入流。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2011-01-02
        • 1970-01-01
        • 2011-10-22
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多