Try... Catch .. Finally file reading

J

John Dann

I'm tripping over a silly little problem when trying to read a text
file, but can't see the fix. Outline code is:

----------------------------------------------------
FS=New FileStream(filename, filemode)
Dim SR as New Streamreader(FS)

Try
Read file
Catch ex as exception
Whatever
Finally
SR.Close()
End Try
-------------------------------------------------

If filename does not exist then the first line above throws an error.

But if I place the FS= and Dim SR lines inside the Try block then SR
seems to go out of scope in the Finally section.

I guess there's several solutions to this like putting the whole code
block inside an If block, ie

If File.Exists(filename) Then
As above
End If

But I can't help feeling I'm missing something obvious in the way this
ought to be done.

JGD
 
J

Jim Hughes

Move the Dim outside of the Try block

Instantiate inside the Try block

You may not need the separate FileStream object, there is an overload for
the StreamReader that will open a file directly. SR =Streamreader(filename)

Dim FS as FileStream
Dim SR as Streamreader
Try
FS=New FileStream(filename, filemode)
SR =Streamreader(FS)
Read file
Catch ex as exception
Whatever
Finally
SR.Close()
End Try
 
I

Imran Koradia

John Dann said:
I'm tripping over a silly little problem when trying to read a text
file, but can't see the fix. Outline code is:

----------------------------------------------------
FS=New FileStream(filename, filemode)
Dim SR as New Streamreader(FS)

Try
Read file
Catch ex as exception
Whatever
Finally
SR.Close()
End Try
-------------------------------------------------

If filename does not exist then the first line above throws an error.

But if I place the FS= and Dim SR lines inside the Try block then SR
seems to go out of scope in the Finally section.

That's because the variable is dimmed within the block and hence is a block
variable. As soon as the block is over, the variable will go out of scope.
In your Try..Catch..Finally, there are 3 blocks - you can define a variable
with the same name in all 3 of them without the compiler throwing errors.
So, you would surely need to define the SR variable outside of the
Try..Catch..Finally block.
I guess there's several solutions to this like putting the whole code
block inside an If block, ie

If File.Exists(filename) Then
As above
End If

This is a good idea - its a good practice to avoid unncessary exceptions
considering the overhead involved. So I would go with this idea of checking
whether the file exists and only then proceed the I/O operation(s).

hope that helps..
Imran.
 
J

John Dann

Many thanks for the answers. I knew the Try...End Try block provided
limited variable scope, but hadn't realised that it amounted to 3
separate blocks.

So I have 2 workable solutions, ie declaring the FS and SR before
starting the Try block or enclosing the whole block in an If
File.Exists container block. But it still strikes me that I don't know
how to encode this simple file access in a fully robust way.

For example if I pre-declare FS and SR but the file doesn't exist then
in my

Finally
SR.Close()

snippet I get a NullReferenceException, presumably (?) because no
valid SR was ever instantiated. So I could catch this specific
exception separately and End Try there.

Maybe I should rethink this approach, but it's just that from VB6 days
one could ensure that a file was closed by allowing the standard code
to run into the error handling code whatever the situation. But maybe
this isn't the best ploy with .Net.

But I find myself still left with the question of how best to protect
and recover from a file read operation in a way that will cope with
all credible error situations.

JGD
 
C

Cor Ligthert

John,

You can as well do this
Try
set your open as you did
Try
do your reading
Catch
error catching while reading...
Finaly
close the file
End Try
Catch
the catch of the open error
End Try

This seems to me robust

I hope this helps?

Cor
 
I

Imran Koradia

How about this:

If File.Exists(filename) Then
Dim FS As New FileStream(filename, filemode)
Dim SR As New StreamReader(FS)
Try
' read file..
Catch ex As Exception
' exception handling..
Finally
SR.Close()
End Try
End If


Is that not what you are looking for?


hope that helps..
Imran.
 
J

John Dann

How about this:

If File.Exists(filename) Then
Dim FS As New FileStream(filename, filemode)
Dim SR As New StreamReader(FS)
Try
' read file..
Catch ex As Exception
' exception handling..
Finally
SR.Close()
End Try
End If


Is that not what you are looking for?

Yes, I agree that in practice that's almost certain to be a good
solution. The residual points - probably rather esoteric ones in
reality - that I wasn't completely happy about were:

1. Whether the file not existing was the only condition that could
conceivably cause SR.Close() to throw an exception (ie are there any
other possible specific circumstances that I should plan for);

2. Whether there was anything else about the file reading operation
that I should be sure to close down in the Finally section in case of
exceptions and, if so, whether these might have their own quirks - as
SR.Close seems to have if SR hasn't been started successfully - that
might throw comparable exceptions of their own.

JGD
 
J

Jay B. Harlow [MVP - Outlook]

John,
In addition to the other comments, I normally check the variable for Nothing
in the Finally clause before calling a method on the variable:
Finally If Not SR Is Nothing Then
SR.Close() End If
End Try

Checking for Nothing first protects you from a NullReferenceException when
the constructor itself threw an exception.

Also in this case I'm not sure you really need the FileStream, you can
simply pass the file name directly to the StreamReader.

Instead of:
FS=New FileStream(filename, filemode)
Dim SR as New Streamreader(FS)
Try

I normally use:
Dim SR as Streamreader
Try
SR = New Streamreader(filename)
Read file
Catch ex as exception
Whatever
Finally If Not SR Is Nothing Then
SR.Close() End If
End Try


Hope this helps
Jay
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top