问题 在读取csv文件时无法移动到下一行


我有一个类帮助我读取一个csv文件,另一个类创建csv的每一行的对象,所以我可以分别为每一行运行一些操作。用它来实现自动化。

由于某种原因我的程序在一行后停止了...之前有效,所以我不知道出了什么问题。

这是我的csv阅读器类:

import java.io.File
import com.github.tototoshi.csv.CSVReader
import jxl.{Cell, Workbook}

import scala.collection.mutable

trait DataSource {

  def read (fileName: String): Seq[Map[String, String]]
}

object CsvDataSource extends DataSource {
  import com.github.tototoshi.csv.CSVFormat
  import com.github.tototoshi.csv.Quoting
  import com.github.tototoshi.csv.QUOTE_MINIMAL

  implicit object MyFormat extends CSVFormat {
    val delimiter: Char = '\t'
    val quoteChar: Char = '"'
    val escapeChar: Char = '"'
    val lineTerminator: String = "\r\n"
    val quoting: Quoting = QUOTE_MINIMAL
    val treatEmptyLineAsNil: Boolean = false
  }

  override def read(file: String): Seq[Map[String, String]] = {
    val reader = CSVReader.open(file, "UTF-16")(MyFormat)
    reader.iteratorWithHeaders.toSeq
  }
}

这是PurchaseInfo类,它正在创建csv的每一行的对象:

case class PurchaseInfo(
                         something1: String,
                         something2: String,
                         something3: String,
                         something4: String) {
}


object PurchaseInfo {

    private def changeDateFormat(dateInString: String): String = {
    //System.out.println(dateInString)
    val formatter: SimpleDateFormat = new SimpleDateFormat("MMM dd, yyyy")
    val formatter2: SimpleDateFormat = new SimpleDateFormat("dd/MM/yyyy")
    val date: Date = formatter.parse(dateInString)
    return formatter2.format(date).toString
  }

    def fromDataSource (ds: DataSource)(fileName: String): Seq[PurchaseInfo] = {

      ds.read(fileName).map { c =>
        PurchaseInfo(
          something1 = c("Supplier Address Street Number"),
          something2 = c("Supplier Address Route"),
          something3 = c("Supplier Address Locality"),
          something4 = c("Supplier Address Postal Code")
        )
      }
    }
}

现在,在我执行所有操作的类中,有一个名为insertData的方法,它获取一系列purchaseInfos,并在此seq中调用每个purchaseInfo的另一个方法....

def insertData (purchaseInfos: Seq[PurchaseInfo]) = {

    //logging in and then getting directed to the right path (where we start the invoices automation)
    login()

    val res = purchaseInfos.map { case purchaseInfo =>
      println(purchaseInfo.invoiceNumber)
      (purchaseInfo, Try(addInvoiceFlow(purchaseInfo)))
    }
    res
  }

问题是insertData调用addInvoiceFlow只有一个与第一个purchaseInfo并停止...为什么?我检查了34行,所以没有csv文件的概率..

这是用scala编写的,但java也可以帮助:)


2774
2017-09-07 11:53


起源

你没有表明如何 purchaseInfos 的论点 insertData 是建造的。您确定该序列中有多个条目吗? - Tim


答案:


我怀疑你在完成阅读之前以某种方式关闭了输入文件。我无法确定,因为您没有提供调用的代码 insertData。要测试此假设,请尝试实现文件内容 read 方法改变

reader.iteratorWithHeaders.toSeq

reader.iteratorWithHeaders.toList

如果之后它会起作用,则表示你关闭了 CSVReader 在使用数据之前。


更新:在我的原始答案中,我对修复是正确的,但在我的解释中并不正确。正如@ som-snytt在他的回答中正确指出的那样, Stream.map 没有实现流,它只是定义了一个实际实现流时应该进行的额外元素转换。因此,在某些情况下,在读取点处不实现流(因此创建中间流)可能是有用的 Map那些随身携带的,而是在地图之后,当实现将直接给你 PurchaseInfos,即

ds.read(fileName).map { c => PurchaseInfo(...)}.force

4
2017-09-09 18:57





你有一系列的 Stream.map。首先 iterator.toSeq 只是 toStream

iteratorWithHeaders.toSeq map PurchaseInfo.apply map addInvoiceFlow

insertData 不会急切地评估调用 addInvoiceFlow,但只有头部元素。

scala> (1 to 10).toStream map { i => println(s"Hi, $i") ; i + 1}
Hi, 1
res0: scala.collection.immutable.Stream[Int] = Stream(2, ?)

所以 insertData 正在返回这个部分评估的流。

你可以强制评估:

scala> res0.force
Hi, 2
Hi, 3
Hi, 4
Hi, 5
Hi, 6
Hi, 7
Hi, 8
Hi, 9
Hi, 10
res1: scala.collection.immutable.Stream[Int] = Stream(2, 3, 4, 5, 6, 7, 8, 9, 10, 11)

还有 这个问题 如果你有一个解析错误。看到 这个评论


6
2017-09-10 00:23





检查行终止符是否为序列 \r\n

它也可能只是 \n

人物 \r 是回车,而 \n 是新行的字符。 Windows使用这对夫妇 \r\n 用于向后兼容dos。

仅限Unix使用 \n


0
2017-09-07 12:00



我试着只使用\ n刚才,它不是它:/ - nick shmick
通常,读取文本文件的Java IO类不关心行结尾。 - a_horse_with_no_name