Scala:getLines 的错误?

Scala : bug with getLines?

我在 scala 中遇到一个非常简单的文件使用问题,我不明白这是错误还是误解了我在做什么... 甚至可以从 scala/eclipse IDE 中的工作表重现。我正在使用 IDE4.6.1 和 scala 2.12.2 代码很简单:

//********************************
import scala.io.Source
import java.io.File
import java.io.PrintWriter

object Embed {

  val filename = "proteins.csv"
  val handler = Source.fromFile(filename)

  val header:String = handler.getLines().next()
  println (">"+header)
  val header2:String = handler.getLines().next()
  println (">"+header2)

  val header3:String = handler.getLines().next()
  println (">"+header3)
}
//**********************

文件的前 3 行有点长,对于非生物专家来说毫无意义:

Protein Group,Protein ID,Accession,Significance,Coverage (%),#Peptides,#Unique,PTM,Cond_A Intensity,Cond_B Intensity,Cond_C Intensity,Cond_D Intensity,Sample Profile (Ratio),Group 1 Intensity,Group 2 Intensity,Group 3 Intensity,Group 4 Intensity,Group Profile (Ratio),Avg. Mass,Description
261,247,P0AFG4|ODO1_ECOL6,200.00,39,30,30,Carbamidomethylation; Deamidation (NQ); Oxidation (M),1.7E5,9.87E4,5.51E4,3.09E4,3.09:1.79:1.00:0.56,1.7E5,9.87E4,5.51E4,3.09E4,3.09:1.79:1.00:0.56,105062,2-oxoglutarate dehydrogenase E1 component OS=Escherichia coli O6:H1 (strain CFT073 / ATCC 700928 / UPEC) GN=sucA PE=3 SV=1
287,657,B7NDL4|MDH_ECOLU,200.00,54,14,1,Carbamidomethylation; Deamidation (NQ); Oxidation (M),6.27E4,4.14E4,1.81E4,1.28E4,3.47:2.29:1.00:0.71,6.27E4,4.14E4,1.81E4,1.28E4,3.47:2.29:1.00:0.71,32336,Malate dehydrogenase OS=Escherichia coli O17:K52:H18 (strain UMN026 / ExPEC) GN=mdh PE=3 SV=1

我不会详细介绍这个文件,但它是一个 3600 行的文件,每行包含 20 个由逗号分隔的字段和一个“”行尾。第一行是 header。 我也试过,只有同样的结果: 第一行读取正确但第二行读取只是文件中第 8 行的最后一部分,依此类推然后我不能 read/parse 我的文件:

下面是我得到的结果

   val filename = "proteins.csv"
                                                  //> filename  : String = proteins.csv
  val handler = Source.fromFile(filename)         //> handler  : scala.io.BufferedSource = non-empty iterator

  val header:String = handler.getLines().next()   //> header  : String = Protein Group,Protein ID,Accession,Significance,Coverage 
                                                  //| (%),#Peptides,#Unique,PTM,Cond_A Intensity,Cond_B Intensity,Cond_C Intensity
                                                  //| ,Cond_D Intensity,Sample Profile (Ratio),Group 1 Intensity,Group 2 Intensity
                                                  //| ,Group 3 Intensity,Group 4 Intensity,Group Profile (Ratio),Avg. Mass,Descrip
                                                  //| tion
  println (">"+header)                            //> >Protein Group,Protein ID,Accession,Significance,Coverage (%),#Peptides,#Uni
                                                  //| que,PTM,Cond_A Intensity,Cond_B Intensity,Cond_C Intensity,Cond_D Intensity,
                                                  //| Sample Profile (Ratio),Group 1 Intensity,Group 2 Intensity,Group 3 Intensity
                                                  //| ,Group 4 Intensity,Group Profile (Ratio),Avg. Mass,Description
  val header2:String = handler.getLines().next()  //> header2  : String = TCC 700928 / UPEC) GN=fumA PE=3 SV=2
  println (">"+header2)                           //> >TCC 700928 / UPEC) GN=fumA PE=3 SV=2

  val header3:String = handler.getLines().next()  //> header3  : String = n SE11) GN=zapB PE=3 SV=1
  println (">"+header3)                           //> >n SE11) GN=zapB PE=3 SV=1

知道我做错了什么吗? 非常感谢您的帮助 别着急:这是尝试使用 scala 的一部分,我现在将返回 Python 完成这项工作!

如果我理解正确的话,问题是每次调用 handler.getLines() 时都会收到一个新的 Iterator[String] 对象,该对象默认指向 CSV 文件的第一行。你应该尝试这样的事情:

val lineIterator = Source.fromFile("proteins.csv").getLines() // Get the iterator object
val firstLine = lineIterator.next()
val secondLine = lineIterator.next()
val thirdLine = lineIterator.next()

或者这样:

val lines = Source.fromFile("proteins.csv").getLines().toIndexedSeq // Convert iterator to the list of lines
val n = 2
val nLine = lines(n)
println(nLine)

你的错误是你调用了三次 handler.getLines()BufferedLineIterator实例化三次并且每个都在调用 next ,这意味着每个实例都试图从同一个源读取。这就是你得到随机输出的原因

正确的方法是只创建一个 handler.getLines() 实例并在其上调用 next

val linesIterator = handler.getLines()

val header:String = linesIterator.next()
println (">"+header)
val header2:String = linesIterator.next()
println (">"+header2)

val header3:String = linesIterator.next()
println (">"+header3)

更准确地说,您甚至不需要通过

来调用 next()
for(lines <- handler.getLines()){
  println(">"+lines)
}