FileIO.TextFieldParser get unaltered row for reporting on failed parse

133 views Asked by At

I want to output the current row if there is an error but I'm getting a message that the current record is nothing.

Here is my code:

Dim currentRow As String()
Using MyReader As New FileIO.TextFieldParser(filenametoimport)
  MyReader.TextFieldType = FileIO.FieldType.Delimited
  MyReader.SetDelimiters(",")

  While Not MyReader.EndOfData
    Try
      currentRow = MyReader.ReadFields()
      ImportLine(currentRow)
    Catch ex As FileIO.MalformedLineException
      report.AppendLine()
      report.AppendLine($"[{currentrow}]")
      report.AppendLine("- record is malformed and will be skipped. ")
      Continue While
    End Try
  End While
end Using

I need to output the currentrow so that I can report to the user that there was a bad record.

report.AppendLine($"[{currentrow}]")

I understand that the value would be null if the parse failed but is there a way to get the current record?

How do I output this record if it failed to parse the record?

Thanks for the assistance!

2

There are 2 answers

0
Joel Coehoorn On BEST ANSWER

You can't get the raw data directly in the exception, but you can at least get the line number where the error occurred. You may be able to use that line number to go back and find the offending record:

Dim currentRow As String()
Using MyReader As New FileIO.TextFieldParser(filenametoimport)
  MyReader.TextFieldType = FileIO.FieldType.Delimited
  MyReader.SetDelimiters(",")

  While Not MyReader.EndOfData
    Try
      currentRow = MyReader.ReadFields()
      ImportLine(currentRow)
    Catch ex As FileIO.MalformedLineException
      report.AppendLine($"{vbCrLf}- record at line {ex.LineNumber} is malformed and will be skipped. ")
    End Try
  End While
End Using

TextFieldParser also provides access to the underlying stream, and provides a ReadLine() method, so if you're really desparate to write the code you could walk back the stream to the previous line ending and then call MyReader.ReadLine() to get the record (which would in turn advance the stream again to where you expect).

3
Mary On

I did not get a compile error on MyReader.SetDelimiters(",") but I changed it to an array anyway. The report.AppendLine($"[{currentrow}]") line probably doesn't expect an array. That line I altered to provide a string.

Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
    Dim currentRow As String() = Nothing
    Using MyReader As New FileIO.TextFieldParser("filenametoimport")
        MyReader.TextFieldType = FileIO.FieldType.Delimited
        MyReader.SetDelimiters({","})

        While Not MyReader.EndOfData
            Try
                currentRow = MyReader.ReadFields()
                ImportLine(currentRow)
            Catch ex As FileIO.MalformedLineException
                report.AppendLine()
                report.AppendLine($"[{String.Join(",", currentRow)}]")
                report.AppendLine("- record is malformed and will be skipped. ")
                Continue While
            End Try
        End While
    End Using
End Sub

EDIT

As per comments by @ Joel Coehoorn and @ ErocM if the row is null you could provide the content of the previous row so they errant row could be located.

        Dim LastGoodRow As String()
        While Not MyReader.EndOfData
            Try
                currentRow = MyReader.ReadFields()
                ImportLine(currentRow)
                LastGoodRow = currentRow
            Catch ex As FileIO.MalformedLineException
                report.AppendLine()
                report.AppendLine($"[{String.Join(",", LastGoodRow)}]")
                report.AppendLine("- record following this row is malformed and will be skipped. ")
                Continue While
            End Try
        End While