Link to home
Start Free TrialLog in
Avatar of username1
username1

asked on

trap error: Input past end of file

Hi,

How to trap error "Input past end of file"?
I tried to use "On Error Goto ..." but not works.
I don't want to pur "If EOF(1) Then" before every "Input" (there are too many data to be input from the file)
Avatar of AzraSound
AzraSound
Flag of United States of America image

why not use a loop that says
Do Until EOF(1)
'code
Loop
Avatar of TSO Fong
The problem with that, AzraSound, is that it's harder to exit the loop before the end of the file has been reached.

If you are reading the 27th item from a file of unknown size, you wouldn't want to have to read the remaining 10,000 items from the file to get to the EOF.

If you're using a for-next loop to read your data, then how about something like this:

On Error Goto AwNuts

Open "C:\File.txt" for Input As #1

For intCount = 1 to intFinal
    Input #1, strA
    Input #1, strB
    Input #1, strC
    Input #1, strD
    ' etc
Next intCount

Close #1

Exit Sub

AwNuts:
If Err.Number = 62 Then
    Resume Next
    intCount = intFinal
End if

Close #1
End Sub



In this way, when it hits EOF, it will pop your loop counter up to the end of your loop, cycle through each remaining input in your loop, and then end. If the error is something other than EOF, you'd need to handle that separately.
i agree with AzraSounds if your hard coding every line input and as you say (there are too many data inputs) then a do until eof(1) is the way to go having generic code in the loop to handle each line input..
whatever value the person wants to read up to, if you reach that value then you just insert

If finalValue Then Exit Do
Avatar of username1
username1

ASKER

Hi AzraSound,

The input data are not the same type and not the same style....difficult to use Do Until EOF(1)...a code example:

'......prior lines
Input #1, strV
For i = 1 to n
  Input #1, intV(i)
Next i
For i = 1 to m
  Input #1, sigV(i)
Next i
'......more lines
how is this data arranged?  are you not reading it line by line?
Hi Experts,

Didn't see your comments when I post the last comment...thank you.

I am using the input files which were stoped by error when creating them. So, in the following code example, the error may happen at any where.

Input #1, strV
For i = 1 to n
  Input #1, intV(i)
Next i
For i = 1 to m
  Input #1, sigV(i)
Next i
i'm still a bit unclear...how is the layout of this datafile?  what info are you trying to draw from it?  would it be plausible to use Line Input instead, read in the data one line at a time, and parse it or whatever you need to do as needed.
Hi AzraSound,

I read the input file line by line, but the data type and the length of the lines are not the same.
i recommend using Line Input...read the whole line in as a string, perform parsing on the string and convert elements that need to be integers and such as needed after parsing using CInt, CLng, CBool as needed.  this way you maintain consistency reading the file, spruce up the parsing code a bit, but allow for simpler file input reading.
Hi AzraSound,

Well.. using Line Input + Parse is too difficult for me :-(  
Nonsense, dont short change yourself  =)

I assume your data is comma - delimited?  what version of vb are you using?
Hi BarryTice,

Don't you noticed I said "I tried to use 'On Error Goto ...' but not works."
I have put that like your code example, but the error "Input past end of file" can still not be handled, it was trapped by VB and stoped my program.
Hi AzraSound,

They are space-delimited.
I am using VB5, there is no the function to separate a line :-( and the stopped point may be anywhere even at the middle of a line....I expect the code for whar you said must more than 10 lines :-)
Private Function SplitFunc(Expression As String, Optional Delimiter As String) As Variant
    Dim i As Long
    Dim lNextPos As Long
    Dim sText As String
    Dim lCount As Long
    Dim varTemp() As String
    For i = 1 To Len(Expression)
       
        lNextPos = InStr(i + 1, Expression, Delimiter)
        If lNextPos = 0 Then
            lNextPos = Len(Expression)
        End If
        sText = Mid$(Expression, i, lNextPos - i)
        ReDim Preserve varTemp(lCount)
        varTemp(lCount) = sText
        lCount = lCount + 1
        i = lNextPos + Len(Delimiter) - 1
       
    Next
    SplitFunc = varTemp
End Function



this will parse your string into an array. it is the equivalent of the Split function of VB6
I often have to read text files with varying record types, multiline records, different parsing requirements, even embedded EOFs to mark separate sections of the same file (archaic mainframe stuff downloaded and merged with PC technology).  I've learned the following basic rules about ambiguous file I/O:
> Job #1 is read the data from the file and control the input flow. You've started to discover this based on your experiences here.  "On Error" works, but as you've noted, with many "Input #1" statements, it gets difficult to manage.
> Job #2 is route the record you just read to the correct parsing routine.
> Job #3 is do with the data what you opened the file for in the first place.
It's a common mistake to think that Job#3 is job#1, and vice versa.  Here's some sample logic, used in a real-world situation: (forgive me, from memory, code is at work right now)


Dim RawBuffer as string
Dim StopTheMadness as Boolean
Dim ReadingRawType as integer
dim BufferParts() as string

On Error goto AwNuts
readingrawtype = 0
StopTheMadness = False
While Not StopTheMadness
   Line Input #1, RawBuffer
   If EOf (1) then
          stopthemadness = true
   else
          Call ParseRawBuffer( RawBuffer, BufferParts, StopTheMadness)
           If readingrawtype = 0 then
               Call DetermineRecordType( BufferParts, ReadingRawType, StopTheMadness)
           endif    
          Select case  ReadingRawType
          case 1
                 Call HandleTypeOne( BufferParts, StopTheMadness)
          case 2
                  Call HandleTypeTwo(BufferParts, StopTheMadness)
          case else
                  Call HandleUnknownType( BufferParts, StopTheMadness)
          end select
  endif
Wend
exit sub ' or whatever follows file input
 Awnuts:
      ' Handle real runtime errors here
end sub


In this design, there is exactly ONE statement inputting data from the file.
Any error condition found by the various routines can stop the input, including EOF, bad/unrecognized data formats, etc.
The "On Error" trap is reserved by  this design for actual runtime errors, and is not used for normal program flow, i.e, what to do when you get to end of file.  My personal preference is to always consider the On Error to be where the program goes when it encounters a condition I didn't design for, or when something really goes wrong external to the code and its data.
Maintenance wise, it's easy to add one more case when a new record type comes along.
Post another question for 100 pts and I'll show you the LAST parser you'll ever need in VB, unless you start reading CSV files in bulk.              
               
I often have to read text files with varying record types, multiline records, different parsing requirements, even embedded EOFs to mark separate sections of the same file (archaic mainframe stuff downloaded and merged with PC technology).  I've learned the following basic rules about ambiguous file I/O:
> Job #1 is read the data from the file and control the input flow. You've started to discover this based on your experiences here.  "On Error" works, but as you've noted, with many "Input #1" statements, it gets difficult to manage.
> Job #2 is route the record you just read to the correct parsing routine.
> Job #3 is do with the data what you opened the file for in the first place.
It's a common mistake to think that Job#3 is job#1, and vice versa.  Here's some sample logic, used in a real-world situation: (forgive me, from memory, code is at work right now)


Dim RawBuffer as string
Dim StopTheMadness as Boolean
Dim ReadingRawType as integer
dim BufferParts() as string

On Error goto AwNuts
readingrawtype = 0
StopTheMadness = False
While Not StopTheMadness
   Line Input #1, RawBuffer
   If EOf (1) then
          stopthemadness = true
   else
          Call ParseRawBuffer( RawBuffer, BufferParts, StopTheMadness)
           If readingrawtype = 0 then
               Call DetermineRecordType( BufferParts, ReadingRawType, StopTheMadness)
           endif    
          Select case  ReadingRawType
          case 1
                 Call HandleTypeOne( BufferParts, StopTheMadness)
          case 2
                  Call HandleTypeTwo(BufferParts, StopTheMadness)
          case else
                  Call HandleUnknownType( BufferParts, StopTheMadness)
          end select
  endif
Wend
exit sub ' or whatever follows file input
 Awnuts:
      ' Handle real runtime errors here
end sub


In this design, there is exactly ONE statement inputting data from the file.
Any error condition found by the various routines can stop the input, including EOF, bad/unrecognized data formats, etc.
The "On Error" trap is reserved by  this design for actual runtime errors, and is not used for normal program flow, i.e, what to do when you get to end of file.  My personal preference is to always consider the On Error to be where the program goes when it encounters a condition I didn't design for, or when something really goes wrong external to the code and its data.
Maintenance wise, it's easy to add one more case when a new record type comes along.
Post another question for 100 pts and I'll show you the LAST parser you'll ever need in VB, unless you start reading CSV files in bulk.              
               
when using line inputs have u tried using the split function this will read a line and split on a char of your choice and return an array of the split out contents..

------------------Help File------------
Description

Returns a zero-based, one-dimensionalarray containing a specified number of substrings.

Syntax

Split(expression[, delimiter[, count[, compare]]])

The Split function syntax has these parts:

Part Description
expression Required.String expression containing substrings and delimiters. If expression is a zero-length string(""), Split returns an empty array, that is, an array with no elements and no data.
delimiter Optional. String character used to identify substring limits. If omitted, the space character (" ") is assumed to be the delimiter. If delimiter is a zero-length string, a single-element array containing the entire expression string is returned.
count Optional. Number of substrings to be returned; –1 indicates that all substrings are returned.
compare Optional. Numeric value indicating the kind of comparison to use when evaluating substrings. See Settings section for values.


Settings

The compare argument can have the following values:

Constant Value Description
vbUseCompareOption –1 Performs a comparison using the setting of the Option Compare statement.
vbBinaryCompare 0 Performs a binary comparison.
vbTextCompare 1 Performs a textual comparison.
vbDatabaseCompare 2 Microsoft Access only. Performs a comparison based on information in your database.


If fields are comma-delimited, a single INPUT #n statement will read the file smoothly.

>>I tried to use "On Error Goto ..." but not works.

Please, ¿could you tell us clearly why it doesn't work?
Hi, username1.

I did read where you said you had tried On Error Goto, but I agree with vikiing's post this morning. What doesn't work about it?

I tested the code that I posted yesterday evening before I posted it to make sure it would work. I opened and wrote one piece of data to a file, then I closed the file. I reopened it and set a loop to read it, with the error trapping as above in place. It worked just fine for me.

Therefore, I assumed that your On Error Goto had been constructed without a means to place you back where you needed to be in your code, and tried to provide a means around that.

Good luck! -- b.r.t.
To vikiing and BarryTice:

1. My example is more complex.

2. Using following BarryTice's example, I read a file with 5 integer separated by space.... Again, I got "Input past end of file" from VB5 and then I got to end the program....you see....

Private Sub Command1_Click()
Dim intA As Integer, intCount As Integer
Const intFinal = 6

On Error GoTo AwNuts

Open "C:\test.txt" For Input As #1

For intCount = 1 To intFinal
    Input #1, intA
Next intCount

Close #1

Exit Sub

AwNuts:
If Err.Number = 62 Then
    Resume Next
    intCount = intFinal
End If

Close #1
End Sub
To vikiing and BarryTice:

The differeces between yours and mine are:

VB6 - VB5?
Integer - String?
my last attempt to encourage you to use Line Input and the SplitFunc I wrote out earlier. it will split up these 5 integers into an array from which you can access each element easily.  then you could easily use the Do Until EOF loop.
To  AzraSound:

I think, until now, your comment is the best one :-)
Note, when I use For loop, I read the data in one single line in the input file. That means, we need to check the number of data after split the line by Line Input to see if we get the correct number of data in the line we expected.

Cheers.
ASKER CERTIFIED SOLUTION
Avatar of AzraSound
AzraSound
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Friend Username1:

1) Sincerely, I don't know why the example you've posted doesn't work; I have VB4, and it runs perfectly

2) A detail: in your error routine, variable intCount never gets a value, 'cause Resume is executed BEFORE, and execution flow returns to the instruction following the error, leaving that assignment instruction without executing.

>If Err.Number = 62 Then
>    Resume Next
>    intCount = intFinal
>End If

3) >>The differeces between yours and mine are:

>>VB6 - VB5?
>>Integer - String?

I can't understand what are those differences you're referring to. :(

Oops. I'm the one who put the intCount after the Resume Next. My bad!
Hi vikiing,

Thank you for still interesing in the problem :-)

I have just tested my example again with the correction that put the line "intCount = intFinal" before "Resume Next" and again it can not work: VB5 gave me the error window with "Input past end of file" and then I got to choose ending the program.

>>VB6 - VB5?
I thought you are using VB6, now I know you using VB4....Can you try VB5? May be my example can only work in VB4?
>>Integer - String?
In my example, the data are integer while in BarryTice's the data are string.

I really hope you are right :-)

Cheers.

Username1
In your error trap routine:

AwNuts:
If Err.Number = 62 Then
    Resume Next
    intCount = intFinal
End if

add a "MsgBox Err.Number" statement to certify:
a) you're really entering error routine
b) error number is that what you expect


>>In my example, the data are integer while in BarryTice's the data are string.

No problem; you can read numeric data into a string variable (although the opposite is not always true).
Hi vikiing,

The key point is VB5 gives the error message before the program calls the error routine!!!! I run the following code again and the program can not display its msgbox.

To understand me, you need to run it under VB5 :-)

Private Sub Command1_Click()

    Dim intA As Integer, intCount As Integer
    Const intFinal = 6

    On Error GoTo AwNuts

    Open "C:\lin\test\test.txt" For Input As #1

    For intCount = 1 To intFinal
        Input #1, intA
    Next intCount

    Close #1

    Exit Sub

AwNuts:
    MsgBox "entering error routine"
'    If Err.Number = 62 Then
'            intCount = intFinal
'        Resume Next
'
'    End If

    Close #1
End Sub
>>The key point is VB5 gives the error message before the program calls the
>>error routine

It sounds as incredible; if that were true, no VB5 program would run properly.

Hey, people (everybody) !!!: this is a terrible behavior from VB5; ¿has anyone experienced the same?
I run VB6, so I can't speak for VB5. But an error there is certainly outside my experience.

I've pasted your code into a VB6 project, and it runs as expected for me.

Good luck!