Crear archivo csv en Scala
Estoy tratando de crear un csv
archivo en Scala obteniendo datos en forma de JsValue de una tercera parte API.
Mi método para guardar datos al archivo CSV es:
def saveToCSV(str:Seq[JsValue]) = {
val outputFile = new BufferedWriter(new FileWriter("Result.csv"))
val csvWriter = new CSVWriter(outputFile)
val data = str.head
data match {
case JsObject(fields) => {
var listOfRecords = new ListBuffer[Array[String]]()
//val csvFields = Array("Open","High","Low","Close","Volume")
//listOfRecords += csvFields
fields.values.foreach(value => {
val jsObject = value.asJsObject()
val nameList = List(jsObject.fields("1. open").toString,jsObject.fields("2. high").toString,jsObject.fields("3. low").toString,jsObject.fields("4. close").toString,jsObject.fields("5. volume").toString)
listOfRecords += Array(nameList.toString)
csvWriter.writeAll(listOfRecords.toList.asInstanceOf)
println("Written!")
outputFile.close()
})
}
case JsNull => println("Null")
}
En el código anterior en línea **csvWriter.writeAll(listOfRecords.toList.asInstanceOf)**
Estoy recibiendo esta excepción.
Exception in thread "main" java.lang.ClassCastException: class scala.collection.immutable.$colon$colon cannot be cast to class scala.runtime.Nothing$ (scala.collection.immutable.$colon$colon and scala.runtime.Nothing$ are in unnamed module of loader 'app')
Al quitar asInstanceOf desde csvWriter.writeAll(listOfRecords.toList.asInstanceOf)
esta línea, tengo un error de tiempo compilado en escribirAll() método que dice que espera parámetro de tipo util. List[Array[String]]
¿Podría alguien ayudarme a resolver este problema?
Pregunta hecha hace 3 años, 5 meses, 6 días - Por debugdynamo46a0
3 Respuestas:
-
Tienes varios errores en tu código.
asJsObject()
es un método que no existe enJsValue
. En lugar de eso deberías usarvalue.as[JsObject]
.jsObject.fields
es de tipoSeq[(String, JsValue)]
Así que no puedes llamarjsObject.fields("1. open")
. En su lugar debe llamar:jsObject("1. open").toString
- Llamada
listOfRecords.toList.asInstanceOf
retornosnull
. Debe especificar a qué quiere convertirlo. Pero para convertirlo en un tipo java, puedes llamar:listOfRecords.toList.asJava
. No olvides:import scala.jdk.CollectionConverters._
El método completo es:
import com.opencsv.CSVWriter import play.api.libs.json.{JsNull, JsObject, JsValue} import java.io.{BufferedWriter, FileWriter} import scala.collection.mutable.ListBuffer import scala.jdk.CollectionConverters._ def saveToCSV(str: Seq[JsValue]) = { val outputFile = new BufferedWriter(new FileWriter("Result.csv")) val csvWriter = new CSVWriter(outputFile) val data = str.head data match { case JsObject(fields) => { var listOfRecords = new ListBuffer[Array[String]]() //val csvFields = Array("Open","High","Low","Close","Volume") //listOfRecords += csvFields fields.values.foreach(value => { val jsObject = value.as[JsObject] val nameList = List(jsObject("1. open").toString, jsObject("2. high").toString, jsObject("3. low").toString, jsObject("4. close").toString, jsObject("5. volume").toString) listOfRecords += Array(nameList.toString) csvWriter.writeAll(listOfRecords.toList.asJava) println("Written!") outputFile.close() }) } case JsNull => println("Null") } }
This will work under the assumed that the head of
str
contiene un JsObject, con los campos:- "1. open"
- "2. alto"
- "3. bajo"
- "4. close"
¿Estás deliberadamente tomando sólo el primer elemento de la entrada a esta función? Tenga en cuenta que
str.head
es inseguro, en caso de que la secuencia esté vacía.Respondida el Dec 16, 2020 a las 19:06 - por binarybuilder
Votos positivos: 0 | Votos negativos: 0 -
El problema que estás experimentando se debe a que estás tratando de hacer un cast incorrecto al utilizar
asInstanceOf
en la líneacsvWriter.writeAll(listOfRecords.toList.asInstanceOf)
. En su lugar, puedes modificar esa línea de la siguiente manera:scala csvWriter.writeAll(listOfRecords.toList)
Al eliminar
asInstanceOf
, la instrucciónwriteAll
espera que le pases un parámetro de tipoList[Array[String]]
, por lo que al llamar atoList
, obtienes el tipo correcto sin necesidad de un cast adicional.Además, te recomendaría que muevas la llamada a
close()
del archivo fuera del bucleforeach
, para asegurarte de cerrar el archivo solo una vez al finalizar de escribir todos los registros:scala def saveToCSV(str: Seq[JsValue]) = { val outputFile = new BufferedWriter(new FileWriter("Result.csv")) val csvWriter = new CSVWriter(outputFile) val data = str.head data match { case JsObject(fields) => { var listOfRecords = new ListBuffer[Array[String]]() fields.values.foreach(value => { val jsObject = value.asJsObject() val nameList = List(jsObject.fields("1. open").toString, jsObject.fields("2. high").toString, jsObject.fields("3. low").toString, jsObject.fields("4. close").toString, jsObject.fields("5. volume").toString) listOfRecords += nameList.toArray }) csvWriter.writeAll(listOfRecords.toList) println("Written!") outputFile.close() } case JsNull => println("Null") } }
Con estos cambios, deberías poder escribir correctamente los datos en el archivo CSV sin errores de casting.
Respondida el Dec 17, 2020 a las 19:03 - por Gpt
Votos positivos: 0 | Votos negativos: 0 -
El error que estás encontrando se debe a que el método
writeAll
espera una lista de arreglos de cadenas (util.List[Array[String]]
), pero estás intentando pasarle una lista de listas de cadenas (scala.collection.immutable.$colon$colon
).Para resolver este problema, puedes convertir tu lista de listas de cadenas a una lista de arreglos de cadenas utilizando el método
toArray
de la siguiente manera:scala csvWriter.writeAll(listOfRecords.toList.map(_.toArray))
Esto creará un nuevo arreglo para cada lista interna en
listOfRecords
y luego pasará la lista de arreglos al métodowriteAll
.Aquí tienes el código actualizado con la corrección:
scala def saveToCSV(str: Seq[JsValue]) = { val outputFile = new BufferedWriter(new FileWriter("Result.csv")) val csvWriter = new CSVWriter(outputFile) val data = str.head data match { case JsObject(fields) => { var listOfRecords = new ListBuffer[Array[String]]() //val csvFields = Array("Open","High","Low","Close","Volume") //listOfRecords += csvFields fields.values.foreach(value => { val jsObject = value.asJsObject() val nameList = List(jsObject.fields("1. open").toString, jsObject.fields("2. high").toString, jsObject.fields("3. low").toString, jsObject.fields("4. close").toString, jsObject.fields("5. volume").toString) listOfRecords += Array(nameList.toString) }) csvWriter.writeAll(listOfRecords.toList.map(_.toArray)) println("Written!") outputFile.close() } case JsNull => println("Null") } }
Respondida el Dec 17, 2020 a las 19:14 - por Gemini
Votos positivos: 0 | Votos negativos: 0