Libor Zapletal
Libor Zapletal

Reputation: 14102

F# Parsing CSV file - find which line is wrong

I wrote this script from some resources I found. It's working but I some files I have problem. I am new in F# so how can I change line with FileHelpersException to get exact line where is the problem? Thanks

// Learn more about F# at http://fsharp.net
// See the 'F# Tutorial' project for more help.
open FileHelpers  
open System

[<DelimitedRecord(",")>]
type CsvRecord =
    class
        val field1 : string
        val field2 : string
        val field3 : int
        new () = {
        field1 = ""
        field2 = ""
        field3 = 0
        }
    end

[<EntryPoint>]
let main argv = 
    use file = System.IO.File.CreateText("result.txt")
    let engine = new FileHelperEngine<CsvRecord>()
    engine.Encoding <- new Text.UTF8Encoding()
    let res = 
       try
          engine.ReadFile("test.csv")
       with
          | :? FileHelpersException -> Array.empty<CsvRecord>
    for record in res do
         fprintfn file "%s" record.field1
    printf "DONE!"
    let s = Console.ReadLine()
    0 // return an integer exit code

Upvotes: 1

Views: 899

Answers (2)

Leaf Garland
Leaf Garland

Reputation: 3687

This question is about the FileHelpers library you are using, not F#, so looking at the docs for that might help. In this case you can check for ConvertException instead of FileHelpersException, which contains members that give you more details about the member.

try
    engine.ReadFile("test.csv")
with
    | :? ConvertException as ex ->
        printfn "ERROR: Line %d Col %d" ex.LineNumber ex.ColumnNumber
        Array.empty<CsvRecord>

I agree with Gustavo though, you might find it easier to use the CsvTypeProvider.

Upvotes: 2

Gustavo Guerra
Gustavo Guerra

Reputation: 5359

I suggest that you use CsvTypeProvider instead. When there's a mismatch the error message states the line which has the error

open FSharp.Data

[<EntryPoint>]
let main argv = 
    use file = System.IO.File.CreateText("result.txt")
    let csv = new CsvProvider<"test.csv">()
    for record in csv.Data do
        fprintfn file "%s" record.field1

If you want to ignore the lines with errors, just pass IgnoreErrors=true as an extra parameter to CsvProvider

Upvotes: 5

Related Questions