简体   繁体   中英

How to create a CSV file and write data into in f#

How can i can i create a csv file in f sharp and write the following record type in it?

    type test = { G:array<double>; P:array<double>; GG:array<double>; PP:array<double> } 

    let table = [for x in 0..(Un0.Length - 1) -> 
        let b = Un0.[x] in 
        if b=0.0 then {G=0.0; P=0.0; GG=0.0; PP=0.0}
        else {G=G_0.[x]/b; P=P0.[x]/b; GG=G0.[x]/b; PP=PP0.[x]/b}]

The CSV type provider from FSharp.Data is primarily known and used for reading CSVs (as the name suggests), but it's also quite capable of writing CSVs as well.

All you need to do is to define the type, either by providing a sample .CSV file

let titanic2 = CsvProvider<"../data/Titanic.csv", Schema="Fare=float,PClass->Passenger Class">.GetSample()

or by directly defining the schema

type MyCsvType = CsvProvider<Schema = "A (int), B (string), C (date option)", HasHeaders=false>

then you can create a record object and populate it (in a type-safe way!)

// you can build the rows themselves
let myCsv = new MyCsvType( [ MyCsvType.Row(1, "a", None)
                             MyCsvType.Row(2, "B", Some DateTime.Now) ])

// or, for your scenario, you probably want to define a conversion function
// from your record type to the CSV provider's type
let buildRowFromObject obj = MyCsvType.Row(obj.A, obj.B, obj.C)

let buildTableFromObjects = (Seq.map buildRowFromObject) >> Seq.toList >> MyCsvType

let myCsv = someSequenceOfObjects |> buildTableFromObjects

and finally, just call

myCsv.SaveToString()

to get the output in CSV format.

To record in .csv is not necessary to use F# Data.

I changed the definition of test and added some values so that you can compile:

type test = { G:double; P:double; GG:double; PP:double }
            override this.ToString() = 
                sprintf "%f;%f;%f;%f\n" this.G this.P this.GG this.PP

let G_0  =  [|(0.0)..(10.0)|]
let Un0  =  [|(1.0)..(11.0)|]
let P0   =  [|(2.0)..(12.0)|]
let G0   =  [|(3.0)..(13.0)|]
let PP0  =  [|(4.0)..(14.0)|]

let table = [for x in 0..(Un0.Length - 1) -> 
                let b = Un0.[x] 
                if b=0.0 then {G=0.0; P=0.0; GG=0.0; PP=0.0}
                else {G=G_0.[x]/b; P=P0.[x]/b; GG=G0.[x]/b; PP=PP0.[x]/b}]

let wr = new System.IO.StreamWriter("Csv.csv")
table |> List.map(string) |> String.concat("") |> wr.Write
wr.Close()

Result:

在此输入图像描述

This is not exactly answer to your question, but it is similar and could be handy

How to EDIT csv file with f# CSV Type Provider

Solution:

#r "..\packages\FSharp.Data.2.3.3\lib\\net40\FSharp.Data.dll"
open System.IO
open FSharp.Data

type CsvTest = CsvProvider<"""C:\Users\User\Desktop\sample.csv""">
let textReader = File.OpenRead("""C:\Users\User\Desktop\sample.csv""")// need to use TextReader
let csvTest = CsvTest.Load(textReader)
let modified = csvTest.Append [CsvTest.Row(3,"bum") ]// add row to csv
textReader.Close()// closing file before edit...
modified.Save   """C:\Users\User\Desktop\sample.csv""" //save it

You may need to Reset Interactive Session (if you work with fsx)

Explanation:

Straightforward file loading like this:

let csvTest = CsvTest.Load("""C:\Users\User\Desktop\sample.csv""")

Does not work. If you try it you will get error:

System.IO.IOException: 'The process cannot access the file 'C:\\Users\\User\\Desktop\\sample.csv' because it is being used by another process.'

So I use TextReader, that can be closed..

Maybe there is easiest solution, but I didn't find any.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM