1
votes

My application is supposed to do the following:

  • Accept a file for input, each line contains 1 record
  • Validate the records
  • Strip any invalid records
  • Pass the remaining data to the database

I'm running into a weird issue where my file contains multiple lines, and if I use the Data Visualizer in Visual Studio the string contains multiple lines, but when I attempt to store the result of String.Split into an array (splitting on \r\n) I only get a single element in my array. Here's a screenshot of my Watch tab:

enter image description here

The first row is my fileContents variable, a string

If I use the Text Visualiser, you can see it's broken out onto separate lines. If I copy and paste that data into note pad, we can see the carriage return & line feed.

The line below that is the fileData array, which populated using String.Split

Here is the actual code:

Private Sub cmdImport_Click(ByVal sender As Object, ByVal e As System.EventArgs) Handles cmdImport.Click
    Dim fileContents As String = GetFileData(pStrBaseDir & pStrFileName)

    Dim linesToExclude As List(Of Int16) = New List(Of Int16)
    mfpScanFile(pStrBaseDir & pStrFileName, pErrorString, pRtfErrString, pStrOutput, linesToExclude)
    'mfpScanFile loops over the file and validates the records, adding the row # to linesToExclude if the row is bad


    'Here we attempt to remove the bad rows
    'First we split the string on new lines into an array
    'Then we clear each line specified by linesToExclude
    Dim splitter As String() = {"\r\n"}
    Dim fileData As String() = fileContents.Split(splitter, StringSplitOptions.RemoveEmptyEntries)
    For i As Int16 = 0 To linesToExclude.Count - 1
        fileData(linesToExclude(i)) = ""
    Next

    fileContents = String.Join("\r\n", fileData)
End Sub


Private Function GetFileData(ByVal strBaseDir As String) As String
    If (Not System.IO.File.Exists(strBaseDir)) Then
        GetFileData = String.Empty
        Exit Function
    End If

    Dim sb As StringBuilder = New StringBuilder()

    For Each line As String In System.IO.File.ReadAllLines(strBaseDir)
        Dim elements As String() = line.Split(",")

        If (Not elements.Length = 15) Then
            GetFileData = "BadCommaCount"
            Exit Function
        End If

        sb.AppendLine(line)
    Next

    GetFileData = sb.ToString()

End Function

So the problem I'm having is that my For loop throws an exception on this line: fileData(linesToExclude(i)) = ""

It throws an exception because fileData only has 1 element. But why it only has 1 element is what I don't understand. The Watch window shows my strings as a single line, but the visualer shows it has line feeds so why isn't my split working?

Furthermore, I have this almost-exact same code in C# and it handles the same file perfectly:

List<int> linesToExclude = new List<int>();
strBadRecs = ScanFile(strBaseDir, ref strErrorString, ref  strRtfErrString, ref strOutput, ref linesToExclude);

// Stripping out bad records
string[] splitter = {"\r\n"};
string[] fileData = objDemographicImport.FileData.Split(splitter, StringSplitOptions.RemoveEmptyEntries);
for (int i = 0; i < linesToExclude.Count; i++)
{
    fileData[linesToExclude[i]] = String.Empty;
}

So what am I doing wrong?

1
"\r\n" doesn't do what you expect in vb. Try using Environment.NewLine or vbCrLf or using the character number.the_lotus
Alternatively.. Why not have GetFileData return a string collection, instead of putting together the collection, joining it into a single string and then splitting it out again?A Friend
@the_lotus argh, that was it. I'll happy accept that as an Answer if you want to post itsab669
@AFriend initially the application simply handed off the location to the DB and let that figure out what was good / bad. I had to tweak it to make the software read the data and send it off to the DB; probably a more elegant way to implement it but that was easiest under the time constraints at the timesab669

1 Answers

3
votes

"\r\n" doesn't do what you expect in vb. Try one of these.

    Dim s1 As String = vbCrLf
    Dim s2 As String = Environment.NewLine
    Dim s3 As String = Chr(13) & Chr(10)

Note that you are doing redundant logic here. You get a list of lines, concatenate them into one string and then split it into a list of lines. Just make GetFileData return a list of line instead of using a StringBuilder.

I did this example without compiling anything, there might be errors.

Private Function GetFileData(ByVal strBaseDir As String) As List(Of String)
    If (Not System.IO.File.Exists(strBaseDir)) Then
        GetFileData = String.Empty
        Return Nothing
    End If

    Dim lines As new List(Of String)

    For Each line As String In System.IO.File.ReadAllLines(strBaseDir)
        Dim elements As String() = line.Split(",")

        If (Not elements.Length = 15) Then
            lines.Clear()
            lines.Add("BadCommaCount")
            Return lines
        End If

        lines.Add(line)
    Next

    Return lines
End Function

Also, "GetFileData = sb.ToString()" can be confusing, I suggest you use Return.