locked
Problem with delimiting .txt files using VB.Net

    Question

  •   I have written a basic application that is used for archival purposes.  It accesses .txt files received daily by my dept, delimits them by commas, and then imports the parsed data into SQL Server.  The app also displays the data from the DB in a form.  I have three buttons to import files from 3 diff org. units, but when I click one in particular, I get this error, and I don't know why.  I highlighted the area that appears to be giving me the problem:

    argument 'length' must be greater or equal to zero.

    Here is some of my parsing code.  Any ideas on why this is happening?:

    If System.IO.File.Exists(FILE_NAME) = True Then 
                Dim objReader As New System.IO.StreamReader(FILE_NAME)  
                Dim objReader2 As New System.IO.StreamReader(FILE_NAME)  
                Dim objStreamWriter As IO.StreamWriter  
                Dim objStreamWriter2 As IO.StreamWriter  
     
                Dim fs As New FileStream(FILE_NAME, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, FileShare.Delete)  
     
                'Pass the file path and the file name to the StreamWriter constructors.  
                objStreamWriter = New IO.StreamWriter(Path)  
                objStreamWriter2 = New IO.StreamWriter(TransLog)  
     
     
                Do While objReader.Peek() <> -1  
                    strTemp = strPrint & objReader.ReadLine()  
     
                    'parse fields from file  
                    str1100 = InStr(strTemp, "{1100}")  
                    str1110 = InStr(strTemp, "{1110}")  
                    str1120 = InStr(strTemp, "{1120}")  
                    str1130 = InStr(strTemp, "{1130}")  
     
                    str1510 = InStr(strTemp, "{1510}")  
                    str1520 = InStr(strTemp, "{1520}")  
                    str3000 = InStr(strTemp, "{3000}")  
                    str3100 = InStr(strTemp, "{3100}")  
                    str3320 = InStr(strTemp, "{3320}")  
                    str3400 = InStr(strTemp, "{3400}")  
                    str3500 = InStr(strTemp, "{3500}")  
                    str3600 = InStr(strTemp, "{3600}")  
                    str3700 = InStr(strTemp, "{3700}")  
                    str3710 = InStr(strTemp, "{3710}")  
                    str3720 = InStr(strTemp, "{3720}")  
     
                    str4000 = InStr(strTemp, "{4000}")  
                    str4100 = InStr(strTemp, "{4100}")  
                    str4200 = InStr(strTemp, "{4200}")  
                    str4320 = InStr(strTemp, "{4320}")  
                    str4400 = InStr(strTemp, "{4400}")  
     
                    str5000 = InStr(strTemp, "{5000}")  
                    str5100 = InStr(strTemp, "{5100}")  
                    str5200 = InStr(strTemp, "{5200}")  
                    str5400 = InStr(strTemp, "{5400}")  
                    str6000 = InStr(strTemp, "{6000}")  
     
                    str6100 = InStr(strTemp, "{6100}")  
                    str6110 = InStr(strTemp, "{6110}")  
                    str6200 = InStr(strTemp, "{6200}")  
                    str6210 = InStr(strTemp, "{6210}")  
                    str6300 = InStr(strTemp, "{6300}")  
                    str6310 = InStr(strTemp, "{6310}")  
                    str6400 = InStr(strTemp, "{6400}")  
                    str6410 = InStr(strTemp, "{6410}")  
                    str6420 = InStr(strTemp, "{6420}")  
                    str6430 = InStr(strTemp, "{6430}")  
                    str6500 = InStr(strTemp, "{6500}")  
     
                    str2000 = InStr(strTemp, "{2000}")  
     
                    'parse field info  
                    str1100 = Mid(strTemp, str1100 + 6, 5)  
                    str1110 = Mid(strTemp, str1110 + 6, 12)  
                    str1120 = Mid(strTemp, str1120 + 6, 34)  
     
                    If str4200 > 0 Then 
                        strSubSet = Mid(strTemp, str4200 + 6, 500)  
                        strEnd = InStr(strSubSet, "{")  
                        str4200 = Mid(strTemp, str4200 + 6, strEnd - 1)  
                    End If 

    Wednesday, December 24, 2008 7:51 PM

Answers

  • See highlighted text.



         Public Function GetValue(ByVal line As String, ByVal id as String) As String
            Dim pos As Integer = InStr(line, "{" & Id & "}")
            Dim nextIdStart as Integer

            If pos > 0 Then
                nextIdStart = Instr(pos, line, "{")    
                If nextIdStart = -1 Then
                    Return Mid(line, pos + Len(Id) + 2, Len(line))
                Else
                    Return Mid(line, pos + Len(Id) + 2, nextIdStart - 1)
                End If
            Else
                Return ""
            End If
        End Function

    Ewald - Please remember to mark the replies as answers if they help.
    • Marked as answer by Xingwei Hu Wednesday, December 31, 2008 2:26 AM
    Friday, December 26, 2008 9:59 PM
  • So, if I wanted to add in StreamReader/StreamWriter methods, would it look like this:

    1 Public Function GetValue(ByVal line As StringByVal id As StringByRef FILE_NAME As StringByRef Path As StringByRef TransLog As StringAs String 
    2  
    3         If System.IO.File.Exists(FILE_NAME) = True Then 
    4             GoTo StartSection  
    5         End If 
    6         Dim objReader As New System.IO.StreamReader(FILE_NAME)  
    7         Dim objReader2 As New System.IO.StreamReader(FILE_NAME)  
    8         Dim objStreamWriter As IO.StreamWriter  
    9         Dim objStreamWriter2 As IO.StreamWriter  
    10  
    11         Dim fs As New FileStream(FILE_NAME, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, FileShare.Delete)  
    12         'Pass the file path and the file name to the StreamWriter constructors.  
    13         objStreamWriter = New IO.StreamWriter(Path)  
    14         objStreamWriter2 = New IO.StreamWriter(TransLog)  
    15         Dim pos As Integer = InStr(line, "{" & id & "}")  
    16         Dim nextIdStart As Integer 
    17  
    18 StartSection:  
    19         If pos > 0 Then 
    20             nextIdStart = InStr(pos, line, "{")  
    21             If nextIdStart = -1 Then 
    22                 Return Mid(line, pos + Len(id) + 2, Len(line))  
    23             Else 
    24                 Return Mid(line, pos + Len(id) + 2, nextIdStart - 1)  
    25             End If 
    26         Else 
    27             Return "" 
    28         End If 
    29     End Function 
    • Marked as answer by Xingwei Hu Wednesday, December 31, 2008 2:26 AM
    Friday, December 26, 2008 10:49 PM

All replies

  • the variable strEnd is evaluated as 0, so you pass to the Mid function the value -1 for the length argument.

    This is not allowed and gives you the ArgumentException.
    Ewald
    Wednesday, December 24, 2008 8:23 PM
  • How do I correct this?
    Wednesday, December 24, 2008 8:28 PM
  • That's up to you.

    When I read your code, then I can see that you are looking in the line of the file to the text {4200}. Then you are reading 500 chars behind the {4200}, and trying to find the first { char again. This is not found and therefore you get the error.

    I assume that the text that is behind the {4200} is more then 500 chars, or there is on { after the {4200}. So it just depends what you want.

    I would do the following:

    If str4200 > 0 Then
        strEnd = Instr(str4200, strTemp, "{")
        If strEnd = -1 Then
            str4200 = Mid(strTemp, str4200 + 6, Len(strTemp))
        Else
            str4200 = Mid(strTemp, str4200 + 6, strEnd - 1)
        End If
    End If


    But I must say that your code is not really what code should be:
    1) You are not declaring variables
    2) the str4200 holds first an integer and then a text
    3) You have far too much variables.

    I would suggest that you create a function to read from the line.

        Public Function GetValue(ByVal line As String, ByVal id as String)
            Dim pos As Integer = InStr(line, "{" & Id & "}")
            Dim nextIdStart as Integer

            If pos > 0 Then
                nextIdStart = Instr(pos, line, "{")    
                If nextIdStart = -1 Then
                    Return Mid(line, pos + Len(Id) + 2, Len(line))
                Else
                    Return Mid(line, pos + Len(Id) + 2, nextIdStart - 1)
                End If
            End If
        End Function


    When you need the value for Id 4200, you can just call the function GetValue(strTemp, "4200")


    Ewald
    Wednesday, December 24, 2008 8:47 PM
  • I did declare the variables in my code, I just couldn't fit everything into the post.  The high number of variables are needed for the number of fields contained within the .txt file.  There are exactly 37 fields in the file, each in the format {1100}, for example.  There are multiple fields per line in the .txt file as well.  So the code was designed to capture all of the information behind each closing bracket } of the desired field and before the next opening bracket { of the following field.  However, each file is not required to contain all 37 fields.  The code had been working for a few wks, but i've had this problem for about two weeks now..Will your suggested function work under these conditions with the multiple fields?
    Wednesday, December 24, 2008 9:17 PM
  • Maybe there are some minor bugs in it, since I didn't test it. But you could try.

    Bottomline I think is that the value after the closing bracket of 4200 is more then 500 characters. Could that be possible?
    Ewald
    Wednesday, December 24, 2008 9:29 PM
  • Yes, this is possible, but the value for field 4200 itself shouldn't reach 500+ characters.  However, the code looks 500 characters beyond the closing bracket of the fields, in this case {4200} and often those 500 characters include other fields.  So I'm then trying to stop at the very next opening bracket following the info I want in the file to make sure I'm pulling back the data for each individual field, one at a time.  Is your GetValue function designed to work with StreamReader/StreamWriter methods?
    Wednesday, December 24, 2008 9:39 PM
  • The code is actually working somewhat as is, because it does create a log file with the information I want.  But it doesnt finish delimiting the entire file for some reason.
    Wednesday, December 24, 2008 9:42 PM
  • Ewald, I tried using the recommended function GetValue, but I got this warning:

    Warning 1 Function 'GetValue' doesn't return a value on all code paths. A null reference exception could occur at run time when the result is used. 
    Friday, December 26, 2008 7:43 PM
  • See highlighted text.



         Public Function GetValue(ByVal line As String, ByVal id as String) As String
            Dim pos As Integer = InStr(line, "{" & Id & "}")
            Dim nextIdStart as Integer

            If pos > 0 Then
                nextIdStart = Instr(pos, line, "{")    
                If nextIdStart = -1 Then
                    Return Mid(line, pos + Len(Id) + 2, Len(line))
                Else
                    Return Mid(line, pos + Len(Id) + 2, nextIdStart - 1)
                End If
            Else
                Return ""
            End If
        End Function

    Ewald - Please remember to mark the replies as answers if they help.
    • Marked as answer by Xingwei Hu Wednesday, December 31, 2008 2:26 AM
    Friday, December 26, 2008 9:59 PM
  • So, if I wanted to add in StreamReader/StreamWriter methods, would it look like this:

    1 Public Function GetValue(ByVal line As StringByVal id As StringByRef FILE_NAME As StringByRef Path As StringByRef TransLog As StringAs String 
    2  
    3         If System.IO.File.Exists(FILE_NAME) = True Then 
    4             GoTo StartSection  
    5         End If 
    6         Dim objReader As New System.IO.StreamReader(FILE_NAME)  
    7         Dim objReader2 As New System.IO.StreamReader(FILE_NAME)  
    8         Dim objStreamWriter As IO.StreamWriter  
    9         Dim objStreamWriter2 As IO.StreamWriter  
    10  
    11         Dim fs As New FileStream(FILE_NAME, FileMode.Open, FileAccess.Read, FileShare.ReadWrite, FileShare.Delete)  
    12         'Pass the file path and the file name to the StreamWriter constructors.  
    13         objStreamWriter = New IO.StreamWriter(Path)  
    14         objStreamWriter2 = New IO.StreamWriter(TransLog)  
    15         Dim pos As Integer = InStr(line, "{" & id & "}")  
    16         Dim nextIdStart As Integer 
    17  
    18 StartSection:  
    19         If pos > 0 Then 
    20             nextIdStart = InStr(pos, line, "{")  
    21             If nextIdStart = -1 Then 
    22                 Return Mid(line, pos + Len(id) + 2, Len(line))  
    23             Else 
    24                 Return Mid(line, pos + Len(id) + 2, nextIdStart - 1)  
    25             End If 
    26         Else 
    27             Return "" 
    28         End If 
    29     End Function 
    • Marked as answer by Xingwei Hu Wednesday, December 31, 2008 2:26 AM
    Friday, December 26, 2008 10:49 PM