Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/391.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/scala/18.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 在Scala中将大型日志文件拆分为多个文件_Java_Scala_Functional Programming_Nio - Fatal编程技术网

Java 在Scala中将大型日志文件拆分为多个文件

Java 在Scala中将大型日志文件拆分为多个文件,java,scala,functional-programming,nio,Java,Scala,Functional Programming,Nio,我有一个很大的日志文件,每个日志行中的一个字段是客户机id。我想将这个大日志文件拆分为几个按客户机id分组的文件。因此,如果原始文件有10行10个唯一的客户机id,那么最后将有10个文件,每个文件中有1行 我尝试在Scala中执行此操作,但不想将整个文件加载到内存中,请使用Scala.io.Source.getLines()一次加载一行。这很有效。但是,我没有一个很好的方法把它一行一行地写在单独的文件中。我可以想出两个选择: 为每一行创建一个由缓冲写入程序(Files.newBufferedWr

我有一个很大的日志文件,每个日志行中的一个字段是客户机id。我想将这个大日志文件拆分为几个按客户机id分组的文件。因此,如果原始文件有10行10个唯一的客户机id,那么最后将有10个文件,每个文件中有1行

我尝试在Scala中执行此操作,但不想将整个文件加载到内存中,请使用Scala.io.Source.getLines()一次加载一行。这很有效。但是,我没有一个很好的方法把它一行一行地写在单独的文件中。我可以想出两个选择:

  • 为每一行创建一个由缓冲写入程序(Files.newBufferedWriter)支持的新PrintWriter。这似乎效率低下

  • 为每个输出文件创建一个由BufferedWriter支持的新PrintWriter,保留这些PrintWriter并继续写入,直到我们读取原始日志文件中的所有行并关闭它们。在Scala中,这似乎不是一种非常实用的方法


  • 作为Scala的新手,我不确定是否还有其他更好的方法来完成类似的任务。非常感谢您的任何想法或想法。

    您可以使用功能强大、惯用的Scala完成第二个选项。您可以跟踪所有的
    打印作者
    ,并在文件行上折叠:

    import java.io._
    import scala.io._
    
    Source.fromFile(new File("/tmp/log")).getLines.foldLeft(Map.empty[String, PrintWriter]) { 
        case (printers, line) =>
            val id = line.split(" ").head
            val printer = printers.get(id).getOrElse(new PrintWriter(new File(s"/tmp/log_$id")))
            printer.println(line)
            printers.updated(id, printer)
    }.values.foreach(_.close)
    

    也许在生产级版本中,您希望将I/O操作包装在一个
    try
    (或
    try
    )中,并以这种方式跟踪故障,同时仍然
    closing
    所有
    PrintWriters

    为什么这是标记Java?我认为(与语言无关),您必须咬紧牙关。或者每行创建一个新的编写器;或者“每个”输出文件创建一个writer——但这意味着所有这些writer都应该保持活动状态(我认为这没有什么大问题;除非我们讨论的是太多的输出writer……以至于应用程序的OS文件句柄都用光了)。我同意@Jägermeister的观点。要添加更多现成的想法,您可以:1.-首先按客户机id对文件进行排序(可能直接使用linux排序),然后每次只需读取1个文件并写入1个文件。2.-使用某种map reduce平台,如Spark,在3行代码中完成这项工作,忘记细节。当然,这完全取决于你的最终目标是什么。这个解决方案对我有效。foldLeft中是否需要“case”关键字,似乎没有它也可以工作?是的--您可以在这里省略
    case