A common task when creating a form based windows application is to allow a user to save their information and to also load saved information. In this short tutorial I will show you the basic steps to save a form’s information to a file and then load up the contents of the saved file.

Saving a Form’s Data to a File

The process for saving data to a file is pretty straightforward in Visual Basic. They include opening up a writer to a specified file, writing the contents, and then closing the writer when completed.

  1. Define and open your File Writer
    In this case we will utilize the StreamWriter class of the System.IO package. I will assume for these instructions that you have imported the System.IO library.
    Dim FileWriter As StreamWriter ' define the stream writer
    
    ' Open the File for writing
    FileWriter = New StreamWriter("c:\temp\sampleFile.txt", False)
  2. Write the desired data to the file
    To write data to the file you can utilize the WriteLine function. In the case of forms you may want to write different data. For a text field saving the Text is appropriate while when using a check box or radio button you will want to save the Checked property.
     ' Save Component values
    FileWriter.WriteLine(textBox.Name & "|" & textBox.Text)
    FileWriter.WriteLine(comboBox.Name & "|" & comboBox.SelectedIndex.ToString())
    FileWriter.WriteLine(radioBtn.Name & "|" & radioBtn.Checked.ToString())
  3. Close and Save your data to the File
    To complete your write you simply need to call Close on your writer. However if you want you can first call Flush to have the data written out. This step is optional however as the Close function will call Flush if needed.
     ' Save and Close File
    FileWriter.Flush() ' optional as close will flush
    FileWriter.Close()

Reading Data from a File

The process for reading information out of a File is similar to the writing process. First you want to open up the file, then you want to read a line of data, single character, or etc depending on how you are going to process the data until you reach the end. After you have read all the data you would lastly close the File.

  1. Define and open your File Reader
    In this case we will utilize the StreamReader class of the System.IO package.
     Dim FileReader As StreamReader   ' define the File Reader
    FileReader = New StreamReader("c:\temp\sampleFile.txt", False)
  2. Iterate until the End of File is reached
    Do Until FileReader.EndOfStream
        ' Processing Code goes here
    Loop
  3. Read in and Process the File’s data
    In the below example we will read in the file’s contents 1 line at a time. To see the full example of how the data is processed please view the full source code below.
    'Read the next line
    prop = FileReader.ReadLine()
  4. Close the File Reader
    After the loop close the FileReader as all the data has been read.
    FileReader.Close()

A complete sample Save and Write Class

For those that learn better by example below is a Simple Class that holds a complete example of saving data to a File from a Form in addition to loading the saved data from the form and setting the components to the correct state. The example contains basic error checking including validating that the saved file exists, however it does not validate the data in the file is of the correct format and not corrupted.

Imports System.IO
 
Public Class Form1
 
    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load
        loadSavedData()
    End Sub
 
    Private Sub CloseButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles CloseButton.Click
        Close() 'Close Application
    End Sub
 
    Private Sub LoadButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles LoadButton.Click
        loadSavedData()
    End Sub
 
    Private Sub loadSavedData()
 
        Dim FileReader As StreamReader   ' define the File Reader
        Dim prop(2) As String            ' define array of length 2

        ' Test if the Saved File exists
        If File.Exists("c:\temp\sampleFile.txt") Then
 
            'Open the File for reading
            FileReader = New StreamReader("c:\temp\sampleFile.txt", False)
 
            ' Continue until EOF reached
            Do Until FileReader.EndOfStream
 
                'Read the next line and split its value based on the | character
                prop = FileReader.ReadLine().Split("|")
 
                ' If TextBox Component set it's property
                If String.Equals(prop(0), textBox.Name) Then
 
                    textBox.Text = prop(1)
 
                    ' If ComboBox Component set it's property
                ElseIf String.Equals(prop(0), comboBox.Name) Then
 
                    comboBox.SelectedIndex = Integer.Parse(prop(1))
 
                    ' If RadioButton set if checked
                ElseIf String.Equals(prop(0), radioBtn.Name) Then
 
                    radioBtn.Checked = Boolean.Parse(prop(1))
 
                ElseIf String.Equals(prop(0), RadioButton1.Name) Then
 
                    RadioButton1.Checked = Boolean.Parse(prop(1))
 
                ElseIf String.Equals(prop(0), RadioButton2.Name) Then
 
                    RadioButton2.Checked = Boolean.Parse(prop(1))
 
                End If
 
            Loop
 
            ' close the file
            FileReader.Close()
 
        End If
 
    End Sub
 
    Private Sub SaveButton_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles SaveButton.Click
 
        Dim FileWriter As StreamWriter ' define the stream writer

        ' Open the File for writing
        FileWriter = New StreamWriter("c:\temp\sampleFile.txt", False)
 
        ' Save Component values
        FileWriter.WriteLine(textBox.Name & "|" & textBox.Text)
        FileWriter.WriteLine(comboBox.Name & "|" & comboBox.SelectedIndex.ToString())
        FileWriter.WriteLine(radioBtn.Name & "|" & radioBtn.Checked.ToString())
        FileWriter.WriteLine(RadioButton1.Name & "|" & RadioButton1.Checked.ToString())
        FileWriter.WriteLine(RadioButton2.Name & "|" & RadioButton2.Checked.ToString())
 
        ' Save and Close File
        FileWriter.Flush() ' optional as close will flush
        FileWriter.Close()
    End Sub
End Class
, , , , , , , ,

Recently I was playing around with the SSL configurations within my PHP Wrapper Library for Harvest API and noticed that I was getting an access error. As it turns out cURL was behaving properly and trying to verify the SSL Certificate of the server, and as no CA Certificate was associated with the library it threw an exception and would fail. Doing some research on the subject I found myself with 2 viable options either download the server certificate and pass that along with my library or simply turn of validation of the SSL certificate. In my case validation is not important so I decided to turn it off.

The CURLOPT_SSL_VERIFYPEER option

One of the standard cURL options defined in PHP is CURLOPT_SSL_VERIFYPEER. This option is used to specify if when the url is SSL enabled if the certificate should be verified. To disable it simply set the option to false for the cURL instance.

$ch = curl_init();
curl_setopt( $ch, CURLOPT_SSL_VERIFYPEER, false );

If you are providing a data feed from your own server instead of accessing one provided by a 3rd party you may want to validate the certificate. In those cases you can find a useful tutorial on how to do so over at unit step.

, , ,

Visual Basic allows multiple methods for concatenating Strings. The simplest and most easily recognized method is using the + operator which will perform the concatenation of Strings. However if you want to concatenate two numbers together you will first have to convert them to Strings to use the + operator. To enable you to specify explicitly that you want to perform a String concatenation Visual Basic has the & operator.

The & operator

The & operator specifies that you want to perform String Concatenation of the objects. Using this operator the objects must be convertible to a String, and if the objects are null then an empty String is returned.

Dim testStr As String
testStr = "My " & "Number: " & 3214

In addition to the & operator you can use the &= operator if you want to append data to the end of a String.

Dim testStr As String
testStr = "Hello"
testStr &= " World"

String Builder

In the case that your application is performing massive String Concatenations then you might get better performance in utilizing the System.Text.StringBuilder Class. This class allows you append, prepend, replace, and in general manipulate the underlying String Data.

Dim sb As New StringBuilder()
sb.Append("Hello")
sb.Append(" World!")
sb.ToString()

String Concatenation is a basic task performed in most applications. Visual Basic enables you to utilize multiple methods for completing the task including the & operator that will force String Concatenation of Integers and Doubles.

, , , ,

Over the lifespan of a software’s code source you will inevitably have to rename functions and properties of classes and maybe even remove them all together. This is not a major issue on simple projects but when your project is used by multiple applications then you may find that you need to keep these deprecated functions until other projects update their code to the new values. The Javadoc deprecated tag is how you mark a function or property as no longer in use and link to the new property or function to use.

The Deprecated Tag

The deprecated tag marks the current property or function as no longer in use. To use the tag simply add it into your Javadoc comments on its own line proceeded by the @ symbol.

/**
 * VIEW - ACTION TYPE
 * @deprecated 
 */
public static final String VIEW = "View";

The Link Tag

When you mark a property or function as deprecated it is always a good idea to link to the new property or function by use of the link tag. You can link to a property/value in the current class or to a property/value in another class.

Link in the current class

/**
 * VIEW - ACTION TYPE
 * @deprecated replaced by {@link #ACTION_VIEW}
 */
public static final String VIEW = "view";

Link in another class

/**
 * filters valid records
 * @deprecated replaced by {@link com.test.TestClass#filter()}
 */

Resources

, , ,

Transferring data between tables is a common task of database maintenance. It is used when updating database schemas or when you need to migrate data to a log or history table. There are 2 common methods for performing the transfer the first is done by use of a WHERE NOT EXISTS sub query, while the less common known method is by setting up and utilizing a Trigger, which removes rows from the old table as soon as they get inserted into the new table.

WHERE NOT EXISTS Method

The most common method of transferring data between tables in a database that i have seen is the combination of ROWCOUNT and a WHERE NOT EXISTS clause. How this method works is that you set your ROWCOUNT to the batch size then you insert into your table to be transferred to from a select of your old table where the current record does not exist in your transfer to table. A sample code snippet showing this method is:

DECLARE @ErrorId INTEGER,
    @RowCtrInserted INTEGER
 
SET ROWCOUNT 10000
 
SELECT @RowCtrInserted = 1, @ErrorId = @@ERROR
 
WHILE (@ErrorId = 0 AND @RowCtrInserted > 0)
BEGIN			
    INSERT INTO LOG_HIST	
        (
        ID,
        USER_EMP_ID,
        APP_NM,
        ACTION_NM,
        ACTION_TS,
        IP_AD
        )
    SELECT 
        ID,
        USER_EMP_ID,
        APP_NM,
        ACTION_NM,
        ACTION_TS,
        IP_AD
    FROM LOG LOG
    WHERE NOT EXISTS (
        SELECT * 
        FROM LOG_HIST hist
        WHERE LOG.ID = hist.ID 
     )
 
    SELECT @RowCtrInserted = @@ROWCOUNT, @ErrorId = @@ERROR
END
 
IF @ErrorId=0 
BEGIN
    TRUNCATE TABLE LOG
END

As can be seen in the code this method loops while a record exists in the log table that is not present in the log_hist table. This requires an additional query every time the batch size is met, and can be a performance problem on large database tables.

Temporary Trigger Method

The second method that can be used to transfer data between two tables is the use of a temporary insert trigger on the table being transferred to. How it works is that the trigger is defined to delete the newly inserted record from the old table. What this means is that for every iteration of the insert loop as determined by the batch size a sub query to determine if a record already exists in the new table is not necessary as records are deleted as soon as they are transferred. Below is a sample sql script setting up the trigger and performing the transfer, in addition it contains error checking and print statements.

CREATE TRIGGER LOG_HIST_TR ON LOG_HIST FOR INSERT
AS
DELETE LOG FROM LOG, inserted
  WHERE 1=1
    AND LOG.ID = inserted.ID
go
 
PRINT "Transferring data from LOG to LOG_HIST"
go
 
DECLARE @err INT, @n INT
SELECT @n=0
PRINT 'Will use batch size of 10000 rows'
WHILE exists (SELECT * FROM LOG)
BEGIN
    INSERT LOG_HIST (
        ID,
        USER_EMP_ID,
        APP_NM,
        ACTION_NM,
        ACTION_TS,
        IP_AD
    )
    SELECT TOP 10000
        ID,
        USER_EMP_ID,
        APP_NM,
        ACTION_NM,
        ACTION_TS,
        IP_AD
    FROM LOG
 
    SELECT @err=@@ERROR, @n=@n+@@ROWCOUNT
 
    IF @err=0
    BEGIN
        DUMP TRAN USERACTIVITY WITH truncate_only
        PRINT '%1! rows transferred', @n
    END
    ELSE
    BEGIN
        RAISERROR 20001 'Failed to transfer data from table LOG to table LOG_HIST. Please recover data from these two tables'
        BREAK
    END
END
 
go
PRINT "Checking data transfer completion"
go
IF not exists (SELECT * FROM LOG)
BEGIN
    DROP TRIGGER LOG_HIST_TR
END
ELSE
BEGIN
    RAISERROR 20001 'Failed to transfer data from LOG into LOG_HIST'
END

In the above example after each batch iteration we output the total number of records transferred, as well as cleaning up the database log so that we don’t max out the allocated space. Once an error is thrown or no more records exists we drop our temporary trigger. You will notice that no truncating of the table we transferred data from is needed as the trigger was responsible for removing them. The additional benefit to using this method is that if a transfer is interrupted no time or data is loss and the transfer can pick up right were it left off without performing an additional WHERE NOT EXISTS sub query.

, , , , , , ,