【问题标题】:How to create a CSV file and write data into in f#如何在 f# 中创建 CSV 文件并将数据写入
【发布时间】:2016-01-09 15:01:01
【问题描述】:

我怎样才能在 f sharp 中创建一个 csv 文件并在其中写入以下记录类型?

    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}]

【问题讨论】:

    标签: f# f#-data


    【解决方案1】:

    CSV type provider from FSharp.Data 主要用于读取 CSV(顾名思义),但它也能够写入 CSV。

    您需要做的就是定义类型,方法是提供一个示例 .CSV 文件

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

    或者直接定义模式

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

    然后您可以创建一个记录对象并填充它(以类型安全的方式!)

    // 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
    

    最后,只需调用

    myCsv.SaveToString()
    

    获取 CSV 格式的输出。

    【讨论】:

    • 有没有办法从现有类型推断 csv 格式(某种自动映射/模式定义)?
    • 这个 csv 会保存在哪里?
    • > 这个 csv 会保存在哪里? .SaveToString() 方法返回一个字符串,并将其保存到任何地方取决于调用者。要在本地保存到磁盘,可以使用 .Save() 函数,该函数需要一个带有路径的字符串,或者一个 TextWriter 或一个将写入内容的 Stream 参数。请参阅:github.com/fsharp/FSharp.Data/blob/… 请注意,在内部 SaveSaveAsString 使用默认设置创建 StringWriter/StreamWriter,因此它使用平台默认换行符。
    【解决方案2】:

    使用 .csv 记录不需要使用 F# 数据。

    我更改了 test 的定义并添加了一些值以便您可以编译:

    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()
    

    结果:

    【讨论】:

    • 这个文件“Csv.csv”保存在哪里?
    • @HaagenDaz,靠近 .exe 文件。但是你可以指定任何路径:System.IO.StreamWriter(PathToFile)
    • @HaagenDaz,对于按索引进行随机访问,数组的工作速度比列表快得多。因此最好使用数组。
    • @FoggyFinder 对于一般的 CSV 写作,最好使用诸如 FSharp.Data 之类的库,因为它会为您处理转义。对于这些特定数据,如果我们忽略本地化,则没有问题。
    • 这不是符合 RFC 4180 的 CSV。例如,它不处理文本和特殊字符转义。甚至分隔符也不是逗号。小数点取决于语言环境。它可能适用于您机器上的 Excel(CSV 实现非常糟糕),但不会产生可移植的 CSV 输出。
    【解决方案3】:

    这不完全是您问题的答案,但它是相似的,可能很方便

    如何使用 f# CSV Type Provider 编辑 csv 文件

    解决办法:

    #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
    

    您可能需要重置交互式会话(如果您使用 fsx)

    解释:

    像这样直接加载文件:

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

    不起作用。如果你尝试它,你会得到错误:

    System.IO.IOException: '进程无法访问文件'C:\Users\User\Desktop\sample.csv',因为它正被另一个进程使用。'

    所以我使用TextReader,可以关闭..

    也许有最简单的解决方案,但我没有找到。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2021-03-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-11-22
      相关资源
      最近更新 更多