在scala中拆分文件

时间:2017-01-13 14:03:37

标签: scala

我想在scala中迭代一个文件并将其拆分为10 000行较小的文件。我怎么能这样做?

def splitFile(file: String, num: Int): Boolean = {
    val buffer = "";
    Source
        .fromFile(file)
        .getLines
        .foreach((line: String, i: Int) => {
            buffer = buffer + line;
            if (i % num == 0) {
                println(i);
            }
        });
};

现在我有类似的东西,但是 - foreach循环没有迭代器。另外,我无法在scala中迭代变量 - cannot reassign variablenot an Int type等。我该怎么做?

4 个答案:

答案 0 :(得分:2)

在具有split二进制文件的* NIX系统上:

import sys.process._
s"split -l 10000 $filename" !

答案 1 :(得分:1)

如果你的文件很大(~500 MB)而且不是巨大的(~5 GB' s)。您可以使用以下功能。

import java.io.{BufferedWriter, File, FileWriter}
import scala.io.Source

def breakFileInPartsOfSizeN(filePath: String, n: Int): Unit = {

  val fileSource = Source.fromFile(filePath)
  val fileSourceLineIterator = fileSource.getLines()

  def getNextBufferedFileWriter(i: Int) = {
    val nextFilePath = filePath + ".part_" + i
    val nextFile = new File(nextFilePath)
    val bfw = new BufferedWriter(new FileWriter(nextFile))
    bfw
  }

  def writeNextNLines(
    i: Int,
    n: Int,
    remaining: Int,
    lineIterator: Iterator[String],
    bufferedFileWriterOption: Option[BufferedWriter] = None
  ): Unit = {
    assert(n >= 0)

    val bufferedFileWriter = (remaining, bufferedFileWriterOption) match {
      case (0, None) => getNextBufferedFileWriter(i + 1)
      case (0, Some(bfw)) =>
        bfw.close()
        getNextBufferedFileWriter(i + 1)
      case (_, None) =>
        getNextBufferedFileWriter(i)
      case (_, Some(bfw)) => bfw
    }

    if (remaining == 0) {
      writeNextNLines(i + 1, n, n, lineIterator, Some(bufferedFileWriter))
    }
    else if (lineIterator.hasNext) {
      val line = lineIterator.next()
      bufferedFileWriter.write(line + System.getProperty("line.separator"))
      writeNextNLines(i, n, remaining - 1, lineIterator, Some(bufferedFileWriter))
    }
    else {
      bufferedFileWriter.close()
      // Well... we are done...
    }
  }

  writeNextNLines(0, n, n, fileSourceLineIterator)

}

现在......你可以像这样使用它

breakFileInPartsOfSizeN("/your/file/absolute/path/filename.txt", 10000)

它将创建名为/your/file/absolute/path/filename.txt.part_n

的零件文件

答案 2 :(得分:0)

首先,如果要改变变量,请使用var而不是valvarval的可变选项 其次,你的foreach似乎错了。请检查以下代码:

Source
  .fromFile(file)
  .getLines
  .foreach { line =>
    buffer = buffer + line
  }

我不太确定您想要的行号,但以下内容应该可以获得由num定义的行数列表

val lines = Source.fromFile(file).getLines.toList
lines.grouped(num).toList

答案 3 :(得分:0)

val step = 10000        
Source.fromFile(file).getLines
  .sliding(step, step)
  .zipWithIndex
  .foreach { case (seq, i) =>
     import java.io._
     val pw = new PrintWriter(new File("filename" + i))
     seq.foreach(pw.println)
     pw.close
   }