Scala 映射大元组列表时从内存中获取java错误

Scala 映射大元组列表时从内存中获取java错误,scala,Scala,我的函数只是简单地获取一个上传的csv文件,并调用另一个函数来清理它并修复它的格式 但是当我用一个非常大的文件(作为字符串)调用我的清理函数时,我得到了一个错误: [错误][24/02/2017][application-scheduler-1] [ActorSystem(应用程序)]来自线程的未捕获错误 [application-scheduler-1]正在关闭JVM,因为 已启用“akka.jvm致命错误退出” java.lang.OutOfMemoryError:超出GC开销限制 这就是它

我的函数只是简单地获取一个上传的csv文件,并调用另一个函数来清理它并修复它的格式

但是当我用一个非常大的文件(作为字符串)调用我的清理函数时,我得到了一个错误:

[错误][24/02/2017][application-scheduler-1] [ActorSystem(应用程序)]来自线程的未捕获错误 [application-scheduler-1]正在关闭JVM,因为 已启用“akka.jvm致命错误退出” java.lang.OutOfMemoryError:超出GC开销限制

这就是它失败的地方:

  def clean(fileStr: String): String = {

    val zippedWithIndex = fileStr.zipWithIndex

    // i need to map it like this for the next stage of my cleaning
    val indexCharMap = zippedWithIndex.map(cur => (cur._2,cur._1)).toMap

    // my string builder
    val builder = new StringBuilder()


...

}
它在
zippedWithIndex.map中失败,因为文件非常大(
fileStr.length
为10948026)

我需要它,因为我在zippedWithIndex上迭代,并且我需要能够在前后检查字符(例如:
indexCharMap.get(chr._2-1))

它只需思考一分钟,然后抛出上面的异常

有什么更好的办法解决这个问题

(除了移动到streams,这将出现在本产品的第二个版本中)

谢谢

现在它是这样工作的:

"Header1","Header2","Header3"

"val"ue1","val"ue2","val"ue"3"
"Header1","Header2","Header3"

"val""ue1","val""ue2","val""ue""3"
我需要一个合适的csv文件,即:

"Header1","Header2","Header3"

"value1","value2","value3"
但是我得到的文件是从某个我无法访问的系统中取出的,并且格式被破坏,这意味着我可以得到这样一个文件:

"Header1","Header2","Header3"

"val"ue1","val"ue2","val"ue"3"
"Header1","Header2","Header3"

"val""ue1","val""ue2","val""ue""3"
这是因为在我获取的值中,可以是引号,而将它们取出来的系统没有进行正确的转义,这应该使它看起来像这样:

"Header1","Header2","Header3"

"val"ue1","val"ue2","val"ue"3"
"Header1","Header2","Header3"

"val""ue1","val""ue2","val""ue""3"
因为csv格式的工作方式是,如果你想有一个非常内在的价值,你需要把双引号

为了解决这个问题,我在zippedWithIndex中迭代,逻辑如下:

 zippedWithIndex.foreach( chr => {

 builder.append(chr._1)

if(!currentlyInsideValue && begginingOfValue(indexCharMap.get(chr._2 - 1)))
        currentlyInsideValue = true

 else if (currentlyInsideValue && endingValue(indexCharMap.get(chr._2 + 1)))
        currentlyInsideValue = false
      else
        builder.append('"')

}

停止使用
zippedWithIndex.map(cur=>(cur.\u 2,cur.\u 1)).toMap中的
toMap
函数。这就是您的GC开销限制超出错误的原因。例如,如下图所示,惰性地处理整个文件

val lines = for {
    (line,index) <- Source.fromFile("output.txt").getLines.zipWithIndex
} yield (line -> index)

def cleaningFunction(currentLine: String, nextLine: String): String = {
   //hypothetical cleaning function
}

val result =  lines.toSeq zip lines.toSeq.tail // stream based sequence to access before/after lines

result.map((x,y) => cleaningFunction(x,y))
val行=用于{
(行、索引)索引
def cleaningFunction(当前行:字符串,下一行:字符串):字符串={
//假设清洁功能
}
val result=lines.toSeq zip lines.toSeq.tail//基于流的序列以访问行前/行后
result.map((x,y)=>cleaningFunction(x,y))

行现在将具有文件的已清理内容,可供以后使用。

看起来您不需要将整个文件保存在内存中,一次只保存一行文本。请尝试下面的程序。在
cleanneline
中编写您自己的代码,以修复一行文本中的引号

import scala.io.Codec
import scala.io.Source
import java.io.PrintWriter

object CSVCleaner {
  val fileName = "Broken.csv"
  val output = "Fixed.csv"

  def main(args: Array[String]) {
    clean(fileName)
  }

  def clean(fileStr: String) {
    val pw = new PrintWriter(output)
    val source = Source.fromFile(fileName)(Codec.ISO8859)
    source.getLines.foreach { line =>
      val clean = cleanOneLine(line)
      pw.print(clean + "\n")
    }
    pw.flush
    pw.close
    source.close
  }

  def cleanOneLine(line: String): String = {
    // your code here
    "put, your, code, here" // ToDo
  }
}

你需要告诉我们关于你想为
indexCharMap
做什么的更多信息?@chengpohi我需要它,因为我在zippedWithIndex上迭代,我需要有能力在前后检查字符(例如:
indexCharMap.get(chr.\u 2-1))
val zippedWithIndex=fileStr.zipWithIndex?这不会为输入字符串中的每个字符创建一个索引吗?这是您真正想要的吗?啊。您上面的评论建议您这样做。确定您的数据非常大。请解释是否需要同时将其全部存储在内存中,或者您可以一次检查一行文件我想我必须立即拥有它,因为我正在修复一个破碎的CSV,形成了一个很好的解决方案,但是在我的例子中,CSV就像我说的那样不好的格式化,而且我在字符串的中间有n的分配,并且GETLIN给我坏了的线……你有其他的解决方案吗,也许我还可以。对整个文件进行eep处理..?听起来你不能保证(我说的“你”是指上游系统)单词不包含双引号或换行符。你能保证什么?如果你能保证“CSV的每一行包含相同的N个列,并且没有字段包含逗号”,你可以将文件预处理为(1)删除所有换行符(2)再次处理文件,并通过计算逗号(3)将其分隔为N列的行逐行处理文件并处理字段内的双引号。但是您需要告诉我们关于此文件可以保证什么。如果没有任何保证,没有人可以确定此输入是否包含一行或两行数据,四行或三行字段:
“a”、“b”、“c”、“d”
。如果一个字段可以包含双引号、逗号和换行符,那么
b“,\n”c
是一个字段,输入包含一行数据,有三个字段。它甚至可以是一行数据,有一个字段。我们需要知道数据有什么保证,否则问题可能无法解决。