Niestrukturalna obsługa wyjątków

advertisement
Niestrukturalna obsługa wyjątków
Do ustawienie pułapkowania błędów w VB 6 stosuje się wyrażenie On Error.
W VB.Net korzysta się z wyrażenia Try ... Catch (aby wyeliminować wyrażenie GoTo)
On Error (Go To) ustawia się przed miejscem, w którym spodziewany jest błąd w jakiejś procedurze.
Zanim pojawi się kod z obsługą błędów pojawić się powinno wyrażenie Exit Sub (aby nie wykonywać
obsługi błędu, kiedy on nie wystąpił)
Obiekt Err istnieje w zasięgu globalnym i zawiera stan błędów, które mogły wystąpić. Własność
Number oddaje numer błędu, własność Description jest opisem błędu
Private Sub drvList_Change()
On Error GoTo driveError
dirList.Path = drvList.Drive
Exit Sub
driveError:
MsgBox Err.Description, vbExclamation, "Drive Error"
End Sub
Wyrażenie Resume
Resume pozwala określić, do którego miejsca powinno wrócić sterowanie wykonaniem programu.
Miejsce to może być określone etykietą albo wyrażeniem Next.
W przypadku Next wykonywanie programu będzie kontynuowane począwszy od wyrażenie
następującego po wyrażeniu powodującym błąd
Private Sub drvList_Change()
On Error GoTo driveError
retryDrive:
dirList.Path = drvList.Drive
Exit Sub
driveError:
Dim response As Integer, description As Integer
description = vbExclamation + vbRetryCancel
response = MsgBox(Err.Description, description, "Drive Error")
If response = vbRetry Then
Resume retryDrive
End If
End Sub
Wyrażenie On Error Resume Next pozwala opuścić wszystkie błędy wykonania,
Wyrażenie On Error GoTo 0 wyłącza pułapkowanie
Private Sub drvList_Change()
On Error Resume Next
dirList.Path = drvList.Drive
End Sub
Zgłaszanie błędu
Do zgłoszenia błędu (ponownego jego zgłoszenia) używa się metody Raise obiektu Err.
description = "Unable to process the data provided"
Err.Raise Err.Number, "myObject", description
W przykładzie obsługiwane są wszystkie błędy, które mogą zostać zgłoszone przez InputBox, za
wyjątkiem niezgodnego typu danych (Error code 13).
Dim age As Integer
On Error GoTo incorrectDataType
age = InputBox("Enter your name", "Age")
Me.Print "You are " & age & " years old"
Exit Sub
incorrectDataType:
If Err.Number = 13 Then
Err.Raise 13
Else
MsgBox Err.description, vbExclamation, "Error"
End If
Strukturalna obsługa błędów (wyjątków)
Wyrzucanie i przechwytywanie wyjątków (zgłaszanie i obsługiwanie)
Wyjątki są obiektami. Służą one do przenoszenia informacji, które generowane są w szczególnych
momentach wykonywania programu. Można powiedzieć, że wyjątek to sygnał, który jest emitowany
w sytuacji krytycznej. Sygnał ten należy przechwycić, aby na sytuację krytyczną odpowiednio
zareagować.
Klasą bazową wszystkich wyjątków jest System.Exception. W środowisku .Net zaimplementowano
szereg klas wyjątków, m.in.:
• ArgumentNullException (używany gdy argumentem metody jest Nothing),
• InvalidCastException, (błędne rzutowanie typu)
• OverflowException, (wystąpienie przepełnienia).
Klasy wyjątków posiadają szereg metod i właściwości. Są to, m.in.:
Message (właściwość tylko do odczytu, ustawiana w konstruktorze podczas tworzenia obiektu
wyjątku)
HelpLink (właściwość do odczytu i zapisu, określająca powiązanie z plikiem pomocy dotyczącego
wyjątku)
StackTrace (właściwość tylko do odczytu ustawiana przez środowisko uruchomieniowe (runtime),
dostarczająca informacje o śladzie stosu dla wyrzucanego błędu (metodach, poprzez które był
propagowany wyjątek)).
Wyrzucanie i przechwytywanie wyjątków jest mechanizmem, który pozwala reagować na krytyczne
sytuacje. Do implementacji tego mechanizmu używa się wyrażenia Throw, obiektu wyjątku oraz bloku
Try...Catch.
Wyrażenie Throw
Throw służy do wyrzucania wyjątków. Aby wyrzucić wyjątek na początek tworzy się obiekt wyjątku, a
następnie obiekt ten przekazuje się do wyrażenia Throw.
Throw New System.Exception( )
Wyrażenie Throw umieszczane jest w metodach. Wykonanie Throw natychmiast kończy metodę, w
której jest umieszczone (podobnie jak Return). Jednak zakończenie działania metody przez
wyrzucenie wyjątku jest przypadkiem specjalnym. Wartość zwraca przez metodę przerwaną przez
wykonanie Throw nie jest określona.
Metody zgłaszające wyjątek mogą być wywoływane wewnątrz innych metod. W takich przypadkach
wyrzucanie wyjątków przez metody wewnętrzne przerywa działanie metod zewnętrznych. Jeśli
zagnieżdżeń wywołań jest więcej, następuje propagacja wyrzucanego wyjątku (i przerywania metod).
Aby zakończyć propagację wyrzucanego wyjątku należy go przechwycić. Jeśli się tego nie zrobi,
program zakończy się błędem.
Option Strict On
Imports System
Namespace ExceptionHandling
Class Tester
Shared Sub Main()
Console.WriteLine("Enter Main...")
Dim t As New Tester
t.Run()
Console.WriteLine("Exit Main...")
End Sub 'Main
Public Sub Run()
Console.WriteLine("Enter Run...")
Func1()
Console.WriteLine("Exit Run...")
End Sub 'Run
Public Sub Func1()
Console.WriteLine("Enter Func1...")
Func2()
Console.WriteLine("Exit Func1...")
End Sub 'Func1
Public Sub Func2()
Console.WriteLine("Enter Func2...")
Throw New System.Exception
Console.WriteLine("Exit Func2...")
End Sub 'Func2
End Class 'Tester
End Namespace 'ExceptionHandling
Wynik działania programu:
Enter Main...
Enter Run...
Enter Func1...
Enter Func2...
Unhandled Exception: System.Exception: Exception of type System.Exception was thrown.
at DebuggingVB.ExceptionHandling.Tester.Func2( ) in C:...\Module1.vb:line 27
at DebuggingVB.ExceptionHandling.Tester.Func1( )
in C:...\Module1.vb:line 21
at DebuggingVB.ExceptionHandling.Tester.Run( )
in C:...\Module1.vb:line 14
at DebuggingVB.ExceptionHandling.Tester.Main( )
in C:...\Module1.vb:line 8
Wyrażenie Try...Catch
Wyrażenie Try..Catch służy do przechwytywania wyjątków. W bloku Try umieszcza się kod, w którym mogą
pojawić się wyjątki, natomiast obsługę wyjątków umieszcza się w bloku Catch. Składnia tego wyrażenia jest
następująca:
Try
[ tryStatements ]
[ Catch [ exception [ As type ] ] [ When expression ]
[ catchStatements ] ]
[ Exit Try ]
...
[ Finally
[ finallyStatements ] ]
End Try
Wiele elementów w powyższym wyrażeniu jest opcjonalnych. Użycie bloku Try...Catch w postaci
generycznej (najprostszej) przedstawia następujący przykład:
Option Strict On
Imports System
Namespace ExceptionHandling
Class Tester
Shared Sub Main()
Console.WriteLine("Enter Main...")
Dim t As New Tester
t.Run()
Console.WriteLine("Exit Main...")
End Sub 'Main
Public Sub Run()
Console.WriteLine("Enter Run...")
Func1()
Console.WriteLine("Exit Run...")
End Sub 'Run
Public Sub Func1()
Console.WriteLine("Enter Func1...")
Func2()
Console.WriteLine("Exit Func1...")
End Sub 'Func1
Public Sub Func2()
Console.WriteLine("Enter Func2...")
Try
Console.WriteLine("Entering Try block...")
Throw New System.Exception
Console.WriteLine("Exitintg Try block...")
Catch
Console.WriteLine("Exception caught and handled")
End Try
Console.WriteLine("Exit func2...")
End Sub 'Func2
End Class 'Tester
End Namespace 'ExceptionHandling
Wynik działania programu (wyjątek wygenerowany w Func2 obsłużony w Func2):
Enter Main...
Enter Run...
Enter Func1...
Enter Func2...
Entering try block...
Exception caught and handled!
Exit Func2...
Exit Func1...
Exit Run...
Exit Main...
Inny przykład (wyjątek wygenerowany w Func2 obsłużony w Func1):
Option Strict On
Imports System
Namespace ExceptionHandling
Class Tester
Shared Sub Main()
Console.WriteLine("Enter Main...")
Dim t As New Tester
t.Run()
Console.WriteLine("Exit Main...")
End Sub 'Main
Public Sub Run()
Console.WriteLine("Enter Run...")
Func1()
Console.WriteLine("Exit Run...")
End Sub 'Run
Public Sub Func1()
Console.WriteLine("Enter func1...")
Try
Console.WriteLine("Entering Try block...")
Func2()
Console.WriteLine("Exiting Try block...")
Catch
Console.WriteLine("Exception caught and handled")
End Try
Console.WriteLine("Exit func1...")
End Sub 'Func1
Public Sub Func2()
Console.WriteLine("Enter Func2...")
Throw New System.Exception
Console.WriteLine("Exit Func2...")
End Sub 'Func2
End Class 'Tester
End Namespace 'ExceptionHandling
Wynik działania programu:
Enter Main...
Enter Run...
Enter Func1...
Entering try block...
Enter Func2...
Exception caught and handled!
Exit Func1...
Exit Run...
Exit Main...
Poza tym, że można w ogóle przechwytywać wyjątki, można jeszcze zdefiniować typ wyjątków jakie
mają zostać przechwycone. Przykład przechwytywania wyjątków konkretnych typów przedstawiony
jest poniżej:
Option Strict On
Imports System
Namespace ExceptionHandling
Class Tester
Public Sub Run()
Try
Dim a As Double = 5
Dim b As Double = 0
Console.WriteLine("Dividing {0} by {1}...", a, b)
Console.WriteLine("{0} / {1} = {2}", _
a, b, DoDivide(a, b))
' most derived exception type first
Catch e As System.DivideByZeroException
Console.WriteLine("DivideByZeroException caught!")
Catch e As System.ArithmeticException
Console.WriteLine("ArithmeticException caught!")
' generic exception type last
Catch
Console.WriteLine("Unknown exception caught")
End Try
End Sub
' do the division if legal
Public Function DoDivide(ByVal a As Double, ByVal b As Double) As Double
If b = 0 Then
Throw New System.DivideByZeroException
End If
If a = 0 Then
Throw New System.ArithmeticException
End If
Return a / b
End Function
Public Shared Sub Main()
Console.WriteLine("Enter Main...")
Dim t As Tester = New Tester
t.Run()
Console.WriteLine("Exit Main...")
End Sub
End Class
End Namespace
Wynik działania programu:
Enter Main...
Dividing 5 by 0...
DivideByZeroException caught!
Exit Main...
Uwaga:
Kolejność umieszczania bloków Catch z konkretnymi typami wyjątków ma znaczenie. Jeśli bowiem
pierwszy z bloków Catch będzie przechwytywał wyjątki klasy nadrzędnej (rodzicielskiej), zaś
pozostałe bloki Catch – wyjątki klas potomnych, to faktycznie nigdy sterowanie nie dojdzie do bloków
Catch z wyjątkami klas potomnych. Powodem jest to, że pierwszy blok Catch dokona obsługi takich
wyjątków (wszędzie tam, gdzie jest referencja do obiektu klasy rodzicielskiej można wstawić
referencję do obiektu klasy potomnej).
W przykładzie powyżej wyjątek DivideByZeroException jest klasą potomną klasy
ArithmeticException. Stąd, jeśli pierwszy blok Catch obsługiwałby wyjątek klasy ArithmeticException,
to sterowanie programem nigdy nie doszłoby do bloku Catch z wyjątkiem typu
DivideByZeroException.
Blok Finally jest blokiem, który jeśli został zadeklarowany, to wykona się zawsze (niezależnie od
tego, czy został wyrzucony wyjątek, czy też nie). W bloku Finally nie można używać Exit, Throw,
Return ani GoTo (tzn. nie można go przerywać wymienionymi instrukcjami).
Option Strict On
Imports System
Namespace ExceptionHandling
Class Tester
Public Sub Run()
Try
Console.WriteLine("Open file here")
Dim a As Double = 5
Dim b As Double = 0
Console.WriteLine("{0} / {1} = {2}", a, b, DoDivide(a, b))
Console.WriteLine("This line may or may not print")
' most derived exception type first
Catch e As System.DivideByZeroException
Console.WriteLine( _
"DivideByZeroException! Msg: {0}", e.Message)
Console.WriteLine( _
"Helplink: {0}", e.HelpLink)
Console.WriteLine( _
"Stack trace: {0}", e.StackTrace)
Catch
Console.WriteLine("Unknown exception caught!")
Finally
Console.WriteLine("Close file here.")
End Try
End Sub 'Run
' do the division if legal
Public Function DoDivide( _
ByVal a As Double, ByVal b As Double) As Double
If b = 0 Then
Dim e As New System.DivideByZeroException
e.HelpLink = "http://www.LibertyAssociates.com"
Throw e
End If
If a = 0 Then
Throw New System.ArithmeticException
End If
Return a / b
End Function 'DoDivide
Shared Sub Main()
Console.WriteLine("Enter Main...")
Dim t As New Tester
t.Run()
Console.WriteLine("Exit Main...")
End Sub 'Main
End Class 'Tester
End Namespace 'ExceptionHandling
Wynik działania programu
Output:
Enter Main...
Open file here
DivideByZeroException! Msg: Attempted to divide by zero.
HelpLink: http://www.libertyassociates.com
Stack trace:
at ExceptionHandling.Tester.DoDivide(Double a, Double b) in ...Module1.vb:line 38
at ExceptionHandling.Tester.Run( ) in ...Module1.vb:line 10
Close file here.
Exit Main...
Wyjątki użytkownika
Aby zaimplementować własny wyjątek (dostarczając mu arbitralnych właściwości i metod) należy
utworzyć klasę wyjątku dziedziczącą po klasie System.ApplicationException. Przykład:
Option Strict On
Imports System
Namespace ExceptionHandling
' custom exception class
Public Class MyCustomException
Inherits System.ApplicationException
Public Sub New(ByVal message As String)
' pass the message up to the base class
MyBase.New(message)
End Sub 'New
End Class 'MyCustomException
Class Tester
Public Sub Run()
Try
Console.WriteLine("Open file here")
Dim a As Double = 0
Dim b As Double = 5
Console.WriteLine("{0} / {1} = {2}", a, b, DoDivide(a, b))
Console.WriteLine("This line may or may not print")
' most derived exception type first
Catch e As System.DivideByZeroException
Console.WriteLine( _
"DivideByZeroException! Msg: {0}", e.Message)
Console.WriteLine("HelpLink: {0}", e.HelpLink)
' catch custom exception
Catch e As MyCustomException
Console.WriteLine( _
"MyCustomException! Msg: {0}", e.Message)
Console.WriteLine("HelpLink: {0}", e.HelpLink)
Catch ' catch any uncaught exceptions
Console.WriteLine("Unknown exception caught")
Finally
Console.WriteLine("Close file here.")
End Try
End Sub 'Run
' do the division if legal
Public Function DoDivide( _
ByVal a As Double, ByVal b As Double) As Double
If b = 0 Then
Dim e As New DivideByZeroException
e.HelpLink = "http://www.libertyassociates.com"
Throw e
End If
If a = 0 Then
' create a custom exception instance
Dim e As New _
MyCustomException("Can't have zero divisor")
e.HelpLink = _
"http://www.libertyassociates.com/NoZeroDivisor.htm"
Throw e
End If
Return a / b
End Function 'DoDivide
Shared Sub Main()
Console.WriteLine("Enter Main...")
Dim t As New Tester
t.Run()
Console.WriteLine("Exit Main...")
End Sub 'Main
End Class 'Tester
End Namespace 'ExceptionHandling
Wynik działania programu:
Enter Main...
Open file here
MyCustomException! Msg: Can't have zero divisor
HelpLink: http://www.libertyassociates.com/NoZeroDivisor.htm
Close file here.
Exit Main...
Uwaga:
Konstruktory nie mogą być dziedziczone, dlatego każda klasa potomna powinna mieć
zaimplementowany własny konstruktor.
************
Visual Basic .NET expands file-handling capabilities while providing compatibility with previous versions of
Visual Basic file I/O functions.
Visual Basic 6.0
In Visual Basic 6.0, file handling is accomplished using various file I/O functions such as Open, Input,
Output, and Append. The File System Object provides an object-oriented method of working with files.
Visual Basic .NET
In Visual Basic .NET, file handling is accomplished through the System.IO namespace, which duplicates and
expands upon the File System Object. In addition, the System.IO.File namespace includes functions that
provide compatibility with the older Visual Basic file I/O functions.
The FileStream class provides access to standard input and output files and error devices.
The following table lists file-related enumerations available in Visual Basic .NET.
Enumeration
FileAccess Enumeration
FileMode Enumeration
FileShare Enumeration
FileAttributes Enumeration
Purpose
Defines constants for read, write, or read/write access
to a file
Specifies how the operating system opens a file
Provides constants for controlling the level of access
other FileStream members have to the same file
Provides access to stored attributes, such as whether a
file is a directory, is encrypted, hidden, or read-only, or
is a system file or a temporary file
Visual Basic allows you to process drives, folders, and files in several different ways: through the use of the
.NET System.IO model, through traditional methods such as the FileOpen and Write functions, and through
the File System Object (FSO) model. The following sections discuss these methods in detail.
The .NET System.IO model provides an object-based tool for working with folders and files. Like
FileSystemObject (as described in Accessing Files with FileSystemObject ), it allows you to use standard
object.method syntax — with its own set of properties, methods, and events — to process text and data, giving
your applications the ability to read from and write to files easily.
The .NET System.IO namespace includes a class library that facilitates string, character, and file manipulation.
These classes contain properties, methods, and events for creating, copying, moving, and deleting files. And,
since both strings and numeric data types are supported, they also allow you to incorporate data types in files.
The most commonly used classes are FileStream, BinaryReader, BinaryWriter, StreamReader, and
StreamWriter.
File Operations
Do operacji na plikach na platformie .NET wprowadzono przestrzeń nazw System.IO.
W przestrzeni tej zawarte są klasy, które pozwalają czytać dane z i pisać dane do plików fizycznych bądź też
strumieni. Są tam też klasy pozwalające wykonywać operacje na systemie plików (jak np. wylistowywanie
katalogów, monitorowanie zmian w systemie plików, itp.). W VB.Net wprowadzono możliwość
asynchronicznego czytania i pisania plików.
Directory Listing
We wcześniejszych wersjach VB do wylistowania katalogów służyła funkcja Dir(). Sposób jej wykorzystania
przedstawia poniższy przykład:
Dim sFile As String
'Obtain an initial value for sFile
sFile = Dir("C:")
'Loop until Dir() returns empty string
Do Until sFile = vbNullString
Debug.Print sFile
sFile = Dir()
Loop
VB 6.0 pozwalał używać Microsoft Scripting Runtime Library. W bibliotece tej udostępniono obiekt
Scripting.FileSystemObject oraz obiekty pochodne. W VB 6.0 realizacja zadania wylistowania katalogów
wyglądała następująco:
'***************************************************
'This example requires a reference to be set to the
'Microsoft Scripting Runtime
'***************************************************
Dim oFS As Scripting.FileSystemObject
Dim oFolder As Scripting.Folder
Dim oFile As Scripting.File
'Create the FileSystemObject Object
Set oFS = New Scripting.FileSystemObject
'Get reference to folder through FileSystemObject
Set oFolder = oFS.GetFolder("C:\")
'Enumerate Files
For Each oFile In oFolder.Files
Debug.Print oFile.Name
Next oFile
W VB.NET udostępniono przestrzeń System.IO. W przestrzeni tej występuje klasa System.IO.Directory, która
odpowiedzialna jest za działania na katalogach, oraz klasa System.IO.File , która służy do wykonywania
operacji na plikach. Oto przykład, jak można wylistować katalog w VB.NET:
Imports SYSTEM.IO
Module Module1
Sub Main()
'Obtain reference to Directory
Dim oDir As Directory = New Directory("C:\")
Dim oFile As File
For Each oFile In oDir.GetFiles()
debug.WriteLine(oFile.Name)
Next
End Sub
End Module
Pliki danych
It is important to consider the type and use of data before storing data in local
files on a client.When accessing data files, you will most likely use ADO and
databases.The benefits of using databases as opposed to binary files are tremendous,
with indexing and sorting and the like built-in. For small amounts of data,
such as configuration data, you may want to store information in the registry.
From the standpoint of debugging, you may want to store the information locally
in a text file—this will allow you to view the information with a simple text
editor such as Notepad.This can aid in the debugging process.That being said,
you may find that sometimes you need to store information in data files on the
client. Data files on the client are usually in binary format. As mentioned earlier
in the chapter, the System.IO namespace is used to provide us with file access
methods. At the top of our module, we need to provide an Imports statement
for System.IO namespace.The following example shows us how to use the
System.IO namespace to perform file I/O to and from a data file.
The BinaryReader and BinaryWriter classes may be more familiar to Visual
Basic users as DataReader and DataWriter from the filesystem object. Although the
names have been changed for the System.IO model, the functionality remains
similar. BinaryReader is used for reading strings and primitive data types, whereas
BinaryWriter writes strings and primitives types from a stream.The following
example demonstrates reading from a binary file and writing to a binary file:
1 Dim InFile As String
2 Dim OutFile As String
3 InFile = "c:\SomeInFile.bin"
4 OutFile = "c:\someOutFile.Bin"
5 Dim inf As New System.IO.File(InFile)
6 Dim outf As New System.IO.File(OutFile)
7 Dim x As Integer
8 Dim aRetVal As Integer
' create streams for input and output
9 Dim myInstream As System.IO.FileStream
10 Dim myOutstream As system.IO.FileStream
11 Dim aFoo(100) As System.Byte ' data to read and write
12 For x = 1 To 99
aFoo(x) = x
13 Next
14 Try
15 myInstream = inf.OpenRead ' Open a new stream for input.
16 myOutStream = outf.OpenWrite
17 aRetVal = myoutstream.write(aFoo, 0, 10)
18 myoutstream.Flush()
19 aRetVal = myInstream.Read(aFoo, 0, 10) ' read 10 bytes
20 Catch IOExcep As IO.IOException
21 ' Some kind of error occurred. Display error message
22 MessageBox.Show(IOExcep.Message)
23 Finally
24 myInStream.Close() ' Close the files
25 myOutStream.Close()
26 End Try
In this code fragment, the file name variables are declared and assigned in
lines 1 through 4.As we progress to lines 5 and 6, the objects for the files are
declared and instantiated. Line 7 declares an integer that will be used later in the
load logic.The stream objects for input and output are created and instantiated.
Line 8 declares an integer to hold the returned value from the call. Lines 9 and
10 initialize the stream variables. In lines 11 through 13, the variable used to send
and receive data is initialized and loaded.We load the variable with numeric data.
Lines 15 and 16 open the streams for reading and writing and associate them
with the files. Line 17 writes some data to the file and line 18 completes the
operation by flushing the buffer.The data written to the file will look like this:
1234567891
Line 19 reads data from the other file (we assume that the file exists; if it
doesn’t exist, we would get an error). Assuming we were to use the file we had
written previously, the data read from the file will look like this:
1234567891
Lines 20 through 26 contain exception-handling code, which will handle any
exceptions that occur. Lines 24 and 25 the close the streams. Line 26 is the end
of the exception-handling code.
That’s all there is to reading and writing to files. Additionally, the filesystem
object provides other methods for file I/O, as do many third-party products.The
filesystem object has been available for use within Visual Basic since Visual Basic
6.0.This is an object that provides methods for manipulating a computer’s files.
The following code fragment demonstrates the use of the filesystem object:
1 Set fs = CreateObject("Scripting.FileSystemObject")
2 Set oFile = fs.CreateTextFile("c:\MyTestFile.txt",
True)
3 oFile.WriteLine("This is a test.")
4 oFile.Close
Pliki tekstowe
The following example shows how to read and write from a text file.This
example opens a file, reads one line at a time from the file, converts the line to
uppercase, and then appends the line to the output file.Writing to and reading
from text files is a common programming task in Visual Basic.
Text files are generally carriage-return delimited and are limited to ASCIIreadable
characters. Data files generally contain control characters:
1 Imports System.ComponentModel
2 Imports System.Drawing
3 Imports System.WinForms
4 Imports SYSTEM.IO
5 Public Class Case_Converter
6 Private LinesCounted As Integer = 0
7 Public Event Status(ByVal LinesCounted As Integer)
8 Public Event FinishedConverting()
9 Sub ToUpper(ByVal InFile As String, ByVal OutFile As String)
' first handle files
10 Dim inf As New SYSTEM.IO.File(InFile)
11 Dim outf As New SYSTEM.IO.File(OutFile)
' create streams for input and output
12 Dim myInstream As SYSTEM.IO.StreamReader
13 Dim myOutstream As SYSTEM.IO.StreamWriter
' temporary string to hold work
14 Dim mystr As String = " " ' initialize to not empty
15 Dim OutStr As String = " "
16 Try
17 myInstream = inf.OpenText ' Open a new stream for input.
' Do until the stream returns Nothing at end of file.
18 myOutStream = outf.CreateText
19 Do Until isnothing(mystr)
20 mystr = myInstream.ReadLine
' perform conversion
21 OutStr = ucase(mystr)
22 myoutstream.WriteLine(OutStr)
23 LinesCounted += 1 ' Increment line count
' raise an event so the form can monitor progress
24 RaiseEvent Status(LinesCounted)
25 Loop
26 Catch eof As IO.EndOfStreamException
' No action is necessary, the end of the stream has been reached.
27 Catch IOExcep As IO.IOException
' Some kind of error occurred.
28 MessageBox.Show(IOExcep.Message)
29 Finally
30 myInStream.Close() ' Close the files
31 myOutStream.Close()
32 End Try
33 RaiseEvent FinishedConverting()
34 End Sub
35 End Class
In this example, we can see that the class Case_Converter contains a method
called ToUpper, which includes two parameters: InFile and OutFile. Note that
importing the System.IO namespace (shown in line 4 of the code) is very important.
This allows us to use the methods and functions contained in that namespace.
Next, as we progress through the code, line 6 declares a local variable for use
within the class. Lines 7 and 8 declare public events that are exploited later in this
chapter. It is good programming practice to declare everything in Visual Basic.
NET for type safety as well as to help understand the data in a particular variable.
Line 9 is the beginning of the method.When we declare the method, notice
that the parameters (InFile and Outfile) include both a type (String) and a calling
method (ByVal).This is very important in Visual Studio .NET because the default
calling type has changed from Byref to Byval, and you may not get the expected
results using the default calling type.
NOTE
Remember to include the Imports System.IO command at the beginning
of your code when you are working with file I/O. If you don’t include it,
your code won’t compile. This is not so much a problem if you are
writing a routine from scratch, because Microsoft’s IntelliSense won’t
work, and you will quickly be aware of the issue. However, look out for if
you are pasting code in from another project.
Lines 10 through 15 declare the objects we use to work with file I/O. Some
important things to note here are the System.IO.File object, the
System.IO.StreamReader object, and the System.IO.StreamWriter object.The
System.IO.File class is used to help create FileStream objects and provides routines
for creating, copying, deleting, moving, and opening of files. In lines 10 and 11,
file objects are created for the input and output files.These are used later with
the FileStream objects that are created in lines 12 and 13.The System.IO
.StreamReader class implements a text reader that will read characters in from the
file.This class does the work when it comes to reading data in from the file.The
System.IO.StreamWriter class implements a text writer that will read characters in
from the file.
Dopisywanie do plików
Appending to files is pretty simple. If we use the code shown in the text files
example, only a minor change is necessary. Appending means that we have an
existing file, and we want to add data to the end of it, which is a common programming
task. Oftentimes, you’ll need to write information out to files for logging,
troubleshooting, and saving information.
17 myInstream = inf.OpenText ' Open a new stream for input.
' Do until the stream returns Nothing at end of file.
18 myOutStream = outf.CreateText
Line 18 would change to:
17 myInstream = inf.OpenText ' Open a new stream for input.
' Do until the stream returns Nothing at end of file.
18 myOutStream = outf.AppendText
Changing the stream type from CreateText to AppendText causes text to be
appended to the file as opposed to overwriting the file.
Download