Posts filed under 'Code Examples'

How To Compare Files in VB.NET

Finding the differences between filesA common function you’ll need when you’re dealing with a lot of files is a way to compare them and report any differences. In this code example, we’ll look at a way of comparing files and capturing the differences between them as we go.

The Design

In this design we’re going to place our CompareFiles routine in a class called FileCompare. The routine itself, CompareFiles, will be a public shared method of the class since we won’t be saving any stateful information. We will also be adding a nested class called FileDifference that will hold the differences we find. Our function will accept the full file names of the two files to compare as string parameters and return a generic list of FileDifference objects.

The Code

First, we’ll look at the code for our function and then discuss a few points in it.

Public Shared Function CompareFiles(ByVal file1 As String, ByVal file2 As String) As List(Of FileDifference)
    Dim ListOfDifferences As New List(Of FileDifference)
    If file1 <> file2 Then
        If File.Exists(file1) AndAlso File.Exists(file2) Then
            Using Stream1 As New FileStream(file1, FileMode.Open), Stream2 As New FileStream(file2, FileMode.Open)
                If Stream1.Length <> Stream2.Length Then
                    ListOfDifferences = Nothing
                Else
                    Dim File1Content As Integer
                    Dim File2Content As Integer
                    Do
                        File1Content = Stream1.ReadByte()
                        File2Content = Stream2.ReadByte()
                        If File1Content <> File2Content Then
                            ListOfDifferences.Add(New FileDifference(File1Content, File2Content, Stream1.Position))
                        End If
                    Loop While (File1Content <> -1)
                End If
            End Using
        Else
            ListOfDifferences = Nothing
        End If
    End If
    Return ListOfDifferences
End Function

If the same file name is passed in for both parameters we’ll return an empty list. If one of the targeted files doesn’t exists or if they are of different lengths, we’ll return Nothing. Otherwise we’ll return the actual differences, if there are any.

Notice that the Using block can work with multiple objects, in this case our two FileStreams. Using will also take care of closing and disposing of the streams. Some people like to throw in a call to the Close method just for good measure. You can add this in just before the End Using if you feel more comfortable having it there.

When the bytes in the file don’t match, we create a new FileDifference object and add it to our list.

Now, let’s take a look at our FileDifference class

Public Class FileDifference
    Private _file1Content As Integer
    Private _file2Content As Integer
    Private _filePosition As Long

    Public Sub New(ByVal content1 As Integer, ByVal content2 As Integer, ByVal position As Long)
        _file1Content = content1
        _file2Content = content2
        _filePosition = position
    End Sub

    Public ReadOnly Property File1Content() As Integer
        Get
            Return _file1Content
        End Get
    End Property

    Public ReadOnly Property File2Content() As Integer
        Get
            Return _file2Content
        End Get
    End Property

    Public ReadOnly Property FilePosition() As Long
        Get
            Return _filePosition
        End Get
    End Property

End Class

There’s nothing that special about this class. It’s just a handy way for us to pass back related values.

When you call this function from your code it would look something like this:

'
'
Dim Differences As List(Of FileCompare.FileDifference)
Differences = FileCompare.CompareFiles(txtFile1.Text, txtFile2.Text)
'
'

Extending It

Of course, this class is just the basics and you will probably want to find ways to extend it for your purposes. For example, you may want to override the ToString function of the FileDifference class to return something you can plug directly into a listbox, such as this:

Public Overrides Function ToString() As String
    Return String.Concat("File 1: 0x", _file1Content.ToString("x"), _
                         " File 2: 0x", _file2Content.ToString("x"), _
                         " at position ", _filePosition)
End Function

You might also want to create a version that deals with text files and compares their contents on a line by line or word by word basis. You could even expand it into a more complex compare and analyze solution if you wanted.

That’s it for this code example. I hope you’ve found it useful. You can click here to download the class file if you wish.. Let me know if you have any questions or observations about this code example by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

1 comment October 3rd, 2007

3 Handy Icon Functions You Can Use

Icon-bot at your serviceThe System.Drawing.Icon class provides several ways for you to work with icons. In this article we’ll look at using its functions to get the icon for a file, creating an icon from a bitmap file, and converting a bitmap to an icon.

Get the Icon for a File

ExtractAssociatedIcon is a shared function that makes it easy to get the icon for a particular file. It will work with any type of file, not just executables. Here’s what the code looks like:

'
'
Me.Icon = Icon.ExtractAssociatedIcon(fileName)
'
'

In this case we’re setting the form icon to the extracted icon, like you might want to do if you had a MDI child form loading a document.

Another common usage is to load the icon into an ImageList control so that you can use it in a ListView or TreeView control. In the example below we’re assuming that we’re loading the contents of a specified folder into a Listview control.

Dim DirInfo As New DirectoryInfo(txtPath.Text)
For Each LookupFile As FileInfo In DirInfo.GetFiles()
    imlFiles.Images.Add(LookupFile.Name, Icon.ExtractAssociatedIcon(LookupFile.FullName))
    lvwFiles.Items.Add(LookupFile.Name, LookupFile.Name)
Next

Note that we retrieve the icon and load it into our ImageList, then load the ListView and point to our newly loaded image by key.

Creating an Icon from a Bitmap File

Let’s suppose you wanted to create an icon for your form from a bitmap image. How would you do that? The FromHandle method allows us to convert a bitmap into an icon. Here’s how to do it.

Private Sub ChangeIcon(ByVal bitmapFilename As String)
    Using IconBitmap As New Bitmap(bitmapFilename)
        Dim HIcon As IntPtr = IconBitmap.GetHicon()
        Using newIcon As Icon = System.Drawing.Icon.FromHandle(HIcon)
            Me.Icon = newIcon
            DestroyIcon(newIcon.Handle)
        End Using
    End Using
End Sub

<System.Runtime.InteropServices.DllImportAttribute("user32.dll")> _
Private Shared Function DestroyIcon(ByVal handle As IntPtr) As Boolean
End Function

First, we load our bitmap file into a bitmap object and get an icon handle. Next we use the FromHandle function to create a new icon and set it to our form’s icon property. The last function, DestroyIcon, is used to free memory used in this process. DestroyIcon is imported in from user32.dll by using InteropServices. Note that we also have Using blocks since we’re working with unmanaged resources.

Converting a Bitmap File to an Icon File

As you can probably guess, the above method could be used to convert a bitmap file into an icon file. To do this you use the Save method of the icon object. Here’s how it works:

Private Sub BitmapToIcon(ByVal bitmapFilename As String, ByVal iconFilename As String)
    Using BaseBitmap As New Bitmap(bitmapFilename)
        Using IconBitmap As New Bitmap(32, 32)
            Using IconGraphics As Graphics = Graphics.FromImage(IconBitmap)
                IconGraphics.DrawImage(BaseBitmap, 0, 0, IconBitmap.Width, IconBitmap.Height)
                Dim HIcon As IntPtr = IconBitmap.GetHicon()
                Using newIcon As Icon = System.Drawing.Icon.FromHandle(HIcon)
                    Using IconStream As New System.IO.FileStream(iconFilename, FileMode.Create)
                        newIcon.Save(IconStream)
                    End Using
                    DestroyIcon(newIcon.Handle)
                End Using
            End Using
        End Using
    End Using
End Sub

The tricky part here is that we need to size the source bitmap to standard icon size, 32×32 pixels. So, to do this, we create a new bitmap and draw the source bitmap to it. We get the icon handle, create a new icon, then create a FileStream with our destination file name, and save the new icon. Once again, we’re using the DestroyIcon function and Using blocks to insure we release resources correctly.

Note that this method isn’t quite complete since it only works with one size of icon (32×32) with 16 colors. More work is needed to have it support more icon formats.

That’s our 3 examples. As I mentioned, they’re just the basics and you will want to work them into your application seamlessly. I don’t recommend just cutting and pasting them in. Take the time to integrate them into your app.

Let me know if you have any questions or suggestions about these routines by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

Add comment October 2nd, 2007

3 Handy VB.NET File Functions You Can Use

File Functions in the 50’sHere are three VB.NET functions you can use for some common file operations. These operations are: Getting the File Attributes, Reading an INI File, and Touching the date/time of a file. By providing wrappers for some of these common .NET functions it makes it easier to add checks and exception handling/prevention to the base routines. These routines are certainly open to expansion and improvement so use them as templates that you can build upon.

Getting File Attributes

Often you’ll find the need to determine the attributes of a file before you perform some action on it. Here’s a handy little function to do just that.

Public Function CheckFileAttribute(ByVal filename As String, ByVal attribute As IO.FileAttributes) As Boolean
    If IO.File.Exists(filename) Then
        If (IO.File.GetAttributes(filename) And attribute) > 0 Then
            Return True
        Else
            Return False
        End If
    Else
        Return False
    End If
End Function

This function checks to see if the target file exists and, if it does, it checks the specified attribute to see if it’s set or not. We’re using the IO.FileAttributes Enum as the second parameter so that we can use the same function to check several different attributes like Hidden, Read-Only, Compressed, or Encrypted.

Note that if the file doesn’t exist a False value is returned. You may want to change this to True depending on how you want your program to flow. Another option would be to make it an optional parameter or an overload where you can decide on the file not found return value.

Here are some example calls:

If CheckFileAttribute(CurrentFile, IO.FileAttributes.Hidden) Then
'
..................
'
If CheckFileAttribute(CurrentFile, IO.FileAttributes.ReadOnly) Then
'
'

Read INI File Contents

Here’s a simple function to read the contents of a standard Windows INI file. The target filename is passed in and a generic list of string array is returned. The list does not contain commented out values but does contain section headers with the value for the header in both elements of the array. The VB.NET TextFieldParser class is used to parse the INI file, using the = sign as a field delimiter. Here’s the function:

Public Function ReadIniFile(ByVal filename As String) As List(Of String())
    Dim IniContents As New List(Of String())
    If Not IO.File.Exists(filename) Then
        Return IniContents
    End If
    Using INIFileParser As FileIO.TextFieldParser = My.Computer.FileSystem.OpenTextFieldParser(filename, "=")
        Dim CurrentLine() As String
        With INIFileParser
            .TrimWhiteSpace = True
            Do While Not INIFileParser.EndOfData
                CurrentLine = .ReadFields()
                If CurrentLine(0).Length > 0 Then
                    Select Case CurrentLine(0).Substring(0, 1)
                        Case ";"
                            'ignore comments
                        Case "["
                            'section header
                            IniContents.Add(New String() {CurrentLine(0), CurrentLine(0)})
                        Case Else
                            IniContents.Add(New String() {CurrentLine(0), CurrentLine(1)})
                    End Select
                End If
            Loop
        End With
    End Using
    Return IniContents
End Function

Note that this is a very simple function. For more sophisticated uses you would probably want to use a class to represent the section and have a list of key/value pair classes as members of that class. Also, some further error condition and parsing logic could be added to insure smoother operation.

Touch

Our last function is a ‘Touch’ function that sets the file dates and times to a specified date. Here’s the function:

Public Function Touch(ByVal filename As String, ByVal newDateTime As Date) As Boolean
    If IO.File.Exists(filename) Then
        IO.File.SetCreationTime(filename, newDateTime)
        IO.File.SetLastWriteTime(filename, newDateTime)
        IO.File.SetLastAccessTime(filename, newDateTime)
    Else
        Return False
    End If
End Function

As you can see, this function sets the creation time, last write time, and last access time to the specified date and returns a True on success and False if the file doesn’t exist. You could expand this function by adding exception handling and more condition checking. You could also do overloaded versions for each date type.

That’s a wrap. Let me know what you think, if you notice any mistakes or if you have any questions by leaving a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

Add comment September 25th, 2007

How To Update Controls Using BackgroundWorker in VB.NET

BackgroundWorker Paints a FormThe .NET Framework 2.0 BackgroundWorker class makes it easy to code simple threading into your applications. However, a common question that gets asked in VB related forums is, “How do I update a control, or controls, from the worker thread?”. Many people seem to be in search of a simple explanation of how to do this. In this article we’ll create a quick and easy example program that will walk you through the steps.

Getting Started

First, we will need to create a new Windows application. On our form we’ll add two buttons, btnStart and btnCancel, a progress bar, prgThread, and a listbox, lstValues. You may also want to import System.ComponentModel into the project namespace or onto the form or you can just spell it out like I’m doing below.

Next we’re going to add code. First, we declare the BackgroundWorker object, TestWorker. Note that we’re declaring it with events so that the event structure is built automatically.

'
Private WithEvents TestWorker As System.ComponentModel.BackgroundWorker
'
'

Now, code is added for the start button, btnStart.

Private Sub btnStart_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnStart.Click
    btnStart.Enabled = False
    btnCancel.Enabled = True
    lstValues.Items.Clear()
    prgThread.Value = 0
    TestWorker = New System.ComponentModel.BackgroundWorker
    TestWorker.WorkerReportsProgress = True
    TestWorker.WorkerSupportsCancellation = True
    TestWorker.RunWorkerAsync()
End Sub

First, we disable the start button and enable the cancel button. Next we reset the values for our listbox and and progressbar. Now we’re ready to create our BackgroundWorker object. Notice that we tell it that we want to have it report progress and support cancellation. Finally, we tell it to run the worker.

The Worker

Here’s the code for our worker thread. This code is contained in the DoWork event. All it’s doing is looping 100 times and reporting the progress and sleeping 100ms between iterations. We also check for a cancellation state.

Private Sub TestWorker_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles TestWorker.DoWork
    Dim ListText As String
    For Value As Integer = 0 To 100
        If TestWorker.CancellationPending Then
            Exit For
        End If
        ListText = String.Concat("Item #", Value)
        TestWorker.ReportProgress(Value, ListText)
        Threading.Thread.Sleep(100)
    Next
End Sub

You can also see that in the ReportProgress function call that we’re passing in the current value and a string.

Updating Form Controls

In the ProgressChanged event, we get to process our values from our DoWork method. Here’s the code:

Private Sub TestWorker_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles TestWorker.ProgressChanged
    prgThread.Value = e.ProgressPercentage
    lstValues.Items.Add(e.UserState)
End Sub
'

In this routine, the progress bar and the listbox are updated with values from the worker thread. Remember that the UserState value is an object and will require conversion if you can’t use an object type.

Canceling the Worker

Now, what if you want to cancel the worker? Here’s the code that goes into our cancel button’s Click event:

Private Sub btnCancel_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnCancel.Click
    TestWorker.CancelAsync()
End Sub
'
'

Here we call the CancelAsync method. However, this only sets a flag and, as shown above, our DoWork method has to check for a CancellationPending state. Otherwise, the work will continue until the DoWork routine is exited.

Finishing Things Up

When the work has been completed or canceled, the RunWorkerCompleted method is called. In our program, this allows us to reset our buttons.

Private Sub TestWorker_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles TestWorker.RunWorkerCompleted
    btnStart.Enabled = True
    btnCancel.Enabled = False
End Sub

That’s how it’s done in a nutshell. Of course, handling multi-threading in your applications can become very tricky. It is recommended that you further review how to avoid problems with threading before implementing it.

Let me know if you have any questions about BackgroundWorker or if you have any suggestions or thoughts about this example by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

24 comments September 24th, 2007

How To Do Credit Card Validation in VB.NET

Pick a card, any cardWhen you’re depending on human interaction to enter a credit card number often you’ll find the user has accidentally typed in the wrong number. That’s why credit card number validation is a common operation in e-commerce web apps and some point-of-sale or order taking desktop apps. By pre-validating the card number a costly round trip to the credit card processor’s system can be avoided.

In this code example we will build a simple validation class that will tell us if a user entered credit card is valid and what type of card it is. I’ll also being using some techniques taken from a few of my recent tutorial articles.

The Luhn Algorithm

Credit card numbers are validated using the Luhn algorithm. This algorithm performs a simple Mod 10 checksum that’s intended to detect accidental errors in a sequence of numbers. For more on this algorithm see the Wikipedia link.

Credit Card Number Format and Test Values

In addition to validating according to Luhn algorithm, credit cards begin with certain numbers and have a certain length. Here are the formats for the four credit card types we’ll be looking at in this example:

  • Visa: 13 or 16 digit numbers starting with 4
  • MasterCard: 16 digit numbers starting with 5
  • Discover: 16 digit numbers starting with 6011 or 65
  • AMEX: 15 digit numbers starting with 34 or 37

For testing purposes you can use these values:

  • 13 Digit Visa: 4222222222222
  • 16 Digit Visa: 4111-1111-1111-1111
  • MasterCard: 5431-1111-1111-1111
  • Discover: 6011-6011-6011-6611
  • AMEX: 341-1111-1111-1111

Coding the Routine

After defining the class, we define an Enum for the credit cards in our example:

Public Class CreditCard

    Public Enum CreditCardTypes
        Invalid = 1
        Visa
        Mastercard
        Discover
        Amex
    End Enum

Notice that we’re going to use the first element as a placeholder for any invalid values. If you wanted to add more cards to the validation routine, just add them at the end of the enum.

Next, we’re going to define a list of regular expression patterns for our supported credit cards. Note that this is a private shared variable.

Private Shared CreditCardPatterns As New List(Of String) _
              (New String() { _
              "^(4\d{12})|(4\d{15})$", _
              "^5[1-5]\d{14}$", _
              "(^(6011)\d{12}$)|(^(65)\d{14}$)", _
              "^3[47]\d{13}$"})

Private Shared _cardNumber As String

As you can see, we’re using a little trick here to initialize our generic list using a string array. Also note that our list matches up with the enum except of the invalid value. This makes it easy to look up our values in the list. Add any new values to the end of the list and make sure the pattern corresponds to the enum.

The Visa regular expression used here is rather simple and you may need more validation to handle all the variations of this card. More complex validation regular expressions can be found at RegExLib.

We will be storing the credit card number at the module level so that we can have access to it in our Predicate function we’ll be using later.

Now, let’s start our Validation routine. In it you’ll see that we’re passing in the card number as a string and returning the card type. Our first order of business is to strip out everything but the digits from our number and declare and initialize our variables.

Public Shared Function Validate(ByVal cardNumber As String) As CreditCardTypes
    Dim CardType As CreditCardTypes = CreditCardTypes.Invalid
    _cardNumber = Regex.Replace(cardNumber, "[^\d]", String.Empty)
    CardType = CType(CreditCardPatterns.FindIndex(AddressOf FindPattern), CreditCardTypes)
    If CardType = CreditCardTypes.Invalid Then
        _cardNumber = String.Empty
        Return CreditCardTypes.Invalid
    End If

Here we see the default return value being set and then our module level variable for the card number being set by using regular expressions to remove all but the numeric values from the string. Next we search for a match to our number by search our pattern list with a Predicate function called FindPattern. Here’s what the Predicate looks like

Private Shared Function FindPattern(ByVal value As String) As Boolean
    If Regex.IsMatch(_cardNumber, value) Then
        Return True
    Else
        Return False
    End If
End Function

As you can see, we use regular expression matching to check our stripped card number value against the pattern. A true or false is returned that the FindIndex function uses to determine if the matching pattern has been found. If the pattern is found, the value is set to the matching enum while it is not, a -1 is returned which matches the invalid enum value.

Now, if we don’t have a match, we return with at this point. If there is a matching pattern, we move on to the Luhn algorithm to test this value further.

    Dim Digits As Char() = _cardNumber.ToCharArray
    _cardNumber = String.Empty
    Dim Digit As Integer
    Dim Sum As Integer = 0
    Dim Alt As Boolean = False
    Array.Reverse(Digits)
    For Each Value As Char In Digits
        Digit = Integer.Parse(Value)
        If Alt Then
            Digit *= 2
            If Digit > 9 Then
                Digit -= 9
            End If
        End If
        Sum += Digit
        Alt = Not Alt
    Next
    _cardNumber = String.Empty
    If Sum Mod 10 = 0 Then
        Return CardType
    Else
        Return CreditCardTypes.Invalid
    End If
End Function

First, we convert our card number string to a character array and initialize our variables and clear out our working variable. Next, we reverse the array. This allows us to use a cleaner For Each method to loop through the array rather than working through it backwards using a counter variable.

Now, we apply the Luhn algorithm to each digit in the array by convert it from a char to an integer and applying the logic to it. After the loop we check the Mod of the Sum and either pass back the card type on True or that it’s an invalid card if False.

That’s all there is to the class, let’s take a look at how it might be called in a button click:

Private Sub btnProcessOrder_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles btnProcessOrder.Click
    Dim CardType As CreditCard.CreditCardTypes = CreditCard.Validate(txtCreditCardNumber.Text)
    If CardType = CreditCard.CreditCardTypes.Invalid Then
        lblStatus.Text = "Not a valid credit card number"
    Else
        lblStatus.Text = String.Concat("Valid ", [Enum].GetName(GetType(CreditCard.CreditCardTypes), CardType), " Credit Card")
    End If
End Sub

Notice that we’re using the [Enum].GetName function to get the text value for our returned enum value.

You can download the code for this example here

Adding to It

There are a number of ways to add to this class. First, it’s implemented as a shared function library. You might want to flesh it out to a full credit card class that would include making calls to a processing service and providing other functionality. Also, you may want to consider some changes to make it thread safe or you might want to add secure string functionality to it. You can also add additional cards or more checking for various card types like I mentioned about the Visa card. Remember this is just a basic example so if you use it you’ll want to adapt it to your situation.

Let me know if you found this example helpful or if I made any mistakes in it or if you have any other observations or questions by leaving me a comment.

Share This Article: These icons link to social bookmarking sites where readers can share and discover new web pages.
  • Digg
  • del.icio.us
  • Reddit
  • StumbleUpon
  • Technorati
  • DotNetKicks
  • DZone

5 comments September 20th, 2007

Next Posts Previous Posts


Visit Me At My New Site, Programming In C#

Most Popular Articles

Highest Rated Articles

Categories

Most Recent Articles

Feeds

 Subscribe in a reader

To subscribe by e-mail
Enter your address here

Delivered by FeedBurner

VB Opportunities

Archives