For your program to keep information from session to session, you must be able to store data on the hard drive. Otherwise, when your application terminates, all the program's data in memory will vanish. Therefore, to have any sort of data persistence, your program must be able to save data to and retrieve data from the hard disk.
You can save data to and retrieve data from disk in several ways. You can use a binary or text file to work with information of varying size and formats. You can read from and write to the Windows Registry to accommodate small bits of binary or text information. Also, you can use a database for more complex persistence issues.
Data lives in computer memory, and a file lives on the hard drive. Your program never works directly with a file on a hard drive. The program asks the operating system to mediate between the hard drive and your program.
You find the location of a file on a hard drive by asking the operating system for a file handle. You use the FreeFile function to obtain a file handle number from the operating system. After you have a file handle, you use the Open statement to assign the handle to the file that you want to write to or read from. When your program hooks up a file handle to a file, it can write data to the file by using the Print (or Write) statement or read lines of data from a file on disk by using the Line Input statement. Figure 19.1 illustrates this concept.
FIGURE 19.1 Writing to a file is the inverse of reading from a file. You still need a file handle, and you need to use the Open statement.
Look at the project AdvTedit.vbp, which you can download from http://www.mcp.com/info. This program is a text editor that uses the Open statement to save and retrieve data from a file on your hard disk.
To use the program, when you want to save data, you click the File menu's Open command. A common dialog appears, into which you enter a filename and select a location on the hard disk. Then you click the common dialog's Save button to commit the data to disk (see Figure 19.2).
FIGURE 19.2 Using the common dialog is an easy way to create a filename and location for your data.
Behind the scenes you're using the Open and Print statements.
The syntax for the Open statement is as follows:
Open FilePath [For Mode] [Access AcessType [LockType] As [#]FileNumber [Len=CharInBuffer%]
In this syntax,
Mode | Description |
Append | Add data to the end of an existing file. If the file doesn't exist, it will be created. |
Binary | Open a file as pure binary--bits and bytes. If the file doesn't exist, it will be created. |
Input | Open file for reading. |
Output | Open file for writing. If the file doesn't exist, it will be created. |
Random | Open file for random access. This is used for simple record storage. If the file doesn't exist, it will be created. |
You open a file for reading as follows:
`Get a free file handle and assign it to `the file handle variable FileHandle% = FreeFile `Open a file for writing Open strFileName For Output As #FileHandle%
Listing 19.1 shows the Click() event procedure for the Save menu item. The procedure opens a file with the Open statement (line 28) and saves the contents of a TextBox to the file by using the Print method (line 34). After the write takes place, the event procedure closes the file by using the Close statement (line 40). The Close statement takes the file handle as an argument.
01 Private Sub itmSave_Click()
02 Dim strFileName As String `String of file to open
03 Dim strText As String `Contents of file
04 Dim strFilter As String `Common Dialog filter string
05 Dim strBuffer As String `String buffer variable
06 Dim FileHandle% `Variable to hold file handle
07
08 `Set the Common Dialog filter
09 strFilter = "Text (*.txt)|*.txt|All Files (*.*)|*.*"
10 cdMain.Filter = strFilter
11
12 `Open the common dialog in save mode
13 cdMain.ShowSave
14
15 `Make sure the retrieved filename is not a blank string
16 If cdMain.filename <> "" Then
17 `If it is not blank, open the file
18 strFileName = cdMain.filename
19
20 `Assign a value to the text variable
21 strText = txtMain.Text
22
23 `Get a free file handle and assign it to the file
24 `handle variable
25 FileHandle% = FreeFile
26
27 `Open a file for writing
28 Open strFileName For Output As #FileHandle%
29
30 `Set an hour glass pointer just in case it takes a while
31 MousePointer = vbHourglass
32
33 `Do the write
34 Print #FileHandle%, strText
35
36 `Reset the pointer to the Windows default.
37 MousePointer = vbDefault
38
39 `Close the file when completed
40 Close #FileHandle%
41 End If
42
43 End Sub
Closing a fileIt's important to remember to Close a file when you're finished with it. The Close statement frees the file handle from memory.
You retrieve data from disk much the same way you write data to disk. The only difference is that, rather than use Append, Output, Binary, or Random mode, you use Input mode. Also, rather than use the Print or Write method to write the data, you read the lines of data in the file, line by line, by using the Line Input statement. The syntax for the Line Input statement is as follows:
Line Input #FileHandle, strBuffer
In this syntax
Simple text files are saved to disk in lines. If you were to do some data entry in NotePad and never press the Enter key, you would have entered one line of code. Every time you press Enter, VB adds the string Chr(13) & Chr(10) (carriage return and line feed) to the TextBox to mark the end of a line; when you save the file, these characters are also written to the file. VB has a constant defined for this string: vbCrLf. The Line Input statement will read into a file until it encounters the end-of-line sequence (vbCrLf). At the end of a line, the statement will take the characters it finds and send them to the string buffer argument, discarding the vbCrLf.
To traverse all the lines in the entire file, use a Do While loop. You use the Visual Basic EOF() function to determine whether the end of the file has been reached. This function takes the file handle number as an argument. As long are you aren't at the end of the file, the Line Input statement continues reading the lines of the file from within the Do While loop.
LEARNING FROM THE ADVTEDIT.VBP PROJECTYou might want to take some time to study the AdvTEdit.vbp project. You can use many useful programming techniques in the code in many situations where you have to accommodate user input and save it to disk.
Listing 19.2 shows the event procedure for the Open menu item from the AdvTedit.vbp project. The user clicks this menu item to open a file into the text editor. The event procedure uses a common dialog to enable the user to identify a file to open.
01 Private Sub itmOpen_Click()
02 Dim strFileName As String `String of file to open
03 Dim strText As String `Contents of file
04 Dim strFilter As String `Common Dialog filter string
05 Dim strBuffer As String `String buffer variable
06 Dim FileHandle% `Variable to hold file handle
07
08 `Set the Common Dialog filter
09 strFilter = "Text (*.txt)|*.txt|All Files (*.*)|*.*"
10 cdMain.Filter = strFilter
11
12 `Open the common dialog
13 cdMain.ShowOpen
14
15 `Make sure the retrieved filename is not a blank string
16 If cdMain.filename <> "" Then
17
18 `If it is not blank, open the file
19 strFileName = cdMain.filename
20
21 `Get a free file handle and assign it to the file
22 `handle variable
23 FileHandle% = FreeFile
24
25 `Open the file
26 Open strFileName For Input As #FileHandle%
27
28 `Make the mouse pointer an hourglass
29 MousePointer = vbHourglass
30
31 `Traverse the lines of the file
32 Do While Not EOF(FileHandle%) `Check for end of file
33
34 `Read a line of the file
35 Line Input #FileHandle%, strBuffer.
36
37 `Add the line from the output buffer
38 strText = strText & strBuffer & vbCrLf
39 Loop
40
41 `Change the mousepointer back to the arrow
42 MousePointer = vbDefault
43
44 `Close the file when completed
45 Close #FileHandle%
46
47 `Assign the retrieved text to the text box
48 txtMain.Text = strText
49
50 `Put the filename in the form caption
51 frmMain.Caption = "Text Editor- [" & strFileName & "]"
52 End If
53 End Sub
As well as save and retrieve text from a file, you can also save and retrieve graphics. You use the LoadPicture() function to load a bitmap or icon file from disk and assign it to the Picture property of a PictureBox or Image control. The syntax for LoadPicture() is as follows:
ImageCtrl.Picture = LoadPicture(FilePath)
In this syntax,
You save a picture that has been assigned to a PictureBox control, Image control, or form by using the SavePicture statement. The syntax for SavePicture is as follows:
SavePicture Picture, strFilePath
In this syntax,
SavePicture has an elementary useBecause of the graphics environment on the Internet and in Windows, you may find yourself using more and more graphics. The SavePicture statement allows you to manipulate, control, and save graphic elements from within your programming code. Manipulating them requires advanced programming skills as well as knowledge of the way Windows handles graphical device contexts. If you want to do advanced graphics work in Visual Basic--even just saving graphic files in multiple formats--you can use many third-party ActiveX controls.
Listing 19.3 shows the SavePicture statement used to save a Picture in an Image control to a location on disk. The program uses a common dialog to determine what to name the file and where to store it. The complete code for this program is in project SaveGrfx.vbp, which you can download from http://www.mcp.com/info.
01 Private Sub cmdImgSave_Click()
02 Dim strFilter As String `common dialog filter
03 Dim strFileName As String `Filename variable
04
05 `Set the CommonDialog filter
06 strFilter = "Bitmaps (*.bmp)|*.bmp"
07
08 `Assign the filter
09 cdMain.Filter = strFilter
10
11 `Show the dialog
12 cdMain.ShowSave
13
14 `Make sure a value was entered in the
15 `common dialog.
16 If cdMain.filename <> "" Then
17 strFileName = cdMain.filename
18
19 `Save the Picture in the image control
20 SavePicture imgMain.Picture, strFileName
21
22 `Tell the user the file's been saved
23 MsgBox strFileName & " saved."
24 End If
25 End Sub
You can use the Windows Registry to store small pieces of information custom to your program. You can use the Registry to store information about the location and size of your program's forms or user preferences. Some programmers use the Registry to store a list of the last files used. No matter what the need is, as long as the information is relatively small, you'll find that using the Registry is a fast, easy way to persist information.
Visual Basic comes with four easy-to-use procedures for accessing the Windows Registry: DeleteSetting, GetSetting, GetAllSettings, and SaveSetting. These internal Registry functions have one major drawback, however--Visual Basic can get and write data only to a specific key in the Registry, MyComputer\HKEY_CURRENT\USER\Software\VB and VBA Program Settings. This process is automatic to VB; Visual Basic can't write to or read from any other keys in the Registry without the aid of the Win32 API functions.
Figure 19.3 shows the location of the Visual Basic applications keys in the Windows Registry.
FIGURE 19.3 When you use the Registry functions internal to VB, data is saved in a key dedicated to all VB and VBA applications.
You use the GetSetting() function to retrieve a value from a particular section in Visual Basic key of the Windows Registry:
MyString = GetSetting(VBKeyName, Section, Key[, Default])
In this syntax,
Thus, the following code snippet
Return$ = GetSetting(App.Title, "FormInit", "Left", DefaultLeft$)
looks for a Registry entry as shown in Figure 19.4. If it fails, it returns the value assigned to the sample string, DefaultLeft$.
FIGURE 19.4 The VB Registry functions can save your data under your program's key.
If you want to save a value to the MyComputer\HKEY_CURRENT\USER\Software\VB and VBA Program Settings key in the Registry, you use the SaveSetting statement:
SaveSetting VBKeyName, Section, Key, Setting
In this syntax,
Hands-on codeFor a detailed look at how to use the SaveSetting statement and the GetSetting() function, look at the user-defined procedures SetFormPos and GetFormPos in the module modAlign.bas in the project Dynamic.vbp, which you can download from http:// www.mcp.com/info.
This procedure relates closely to the GetSetting() function--it's the inverse. Whereas you use GetSetting() to retrieve a VB value from a specified key in the Registry, you use SaveSetting to set a value to the given VB key. All arguments, except for the last one, are identical.
Thus, the following code snippet
SaveSetting App.Title, "FormInit", "Left", "975"
produces the Registry setting shown in Figure 19.4.
You use the Visual Basic function GetAllSettings() to retrieve an array from the Registry that contains all the key settings and those keys' respective values of a particular section within MyComputer\HKEY_CURRENT\USER\Software\VB and VBA Program Settings. The syntax for GetAllSettings() is as follows:
MyVariant = GetAllSettings(VBKeyName, Section)
In this syntax
When you use GetAllSettings(), the function returns a two-dimensional array in the form of a variant. To obtain the values, you transverse the array as you would any other.
If you want to delete an entire section from a key, you use the DeleteSetting statement:
DeleteSetting VBKeyName, Section[, Key]
In this syntax,
Thus, the following code snippet
DeleteSetting App.Title, "FormInit
deletes the Registry setting shown in Figure 19.4.
File system objects versus FileSystemObjectsThe file system objects are all the objects that enable you to work with the file system of a computer: the Drive, Folder, File, TextStream, and FileSystemObject objects. The FileSystemObject is a central object that gives you access to the various file system objects by way of a return from the various methods of the FileSystemObject.
New to Visual Basic 6 are the file system objects, which encapsulate the objects, methods, and data that you use to work with files, directories, and drives within a computer's file system. Before you can use the file system objects, you must add the DLL that contains the object into the Visual Basic IDE. After you open the References dialog (choose References from the Project menu), select Microsoft Scripting Runtime (SCRRUN.DLL). This process is similar to adding any COM object to the VB IDE (see Figure 19.5).
FIGURE 19.5 You can use the file system objects to access methods and objects necessary to work with files on your hard drive.
Table 9.2 shows the various file system objects.
Name | Description |
Drive | Enables you to access various drives on a system. These drives can be CD-ROM drives, RAM disks, or mapped network drives. |
Folder | Enables you to work with folders (directories) on a system. You can find out names and location. You also can create and delete folders with methods of the Folder object. |
File | Enables you to open, create, or move files. |
FileSystemObject | The central file system object. You use the FileSystemObject to access other file system objects. |
TextStream | Enables you to read, write, and append text files. |
Working with objectsTo receive the full benefit of the FileSystemObject, you need to have a basic knowledge of object-oriented programming (OOP). For an overview of OOP, read Chapter 26, "Making Object-Oriented Programs with Visual Basic."
You declare a FileSystemObject by using the New keyword. Thus, to make the fso FileSystemObject, you use the following code:
Dim fso As New FileSystemObject
When you have a FileSystemObject, you can use that object to access other file system objects, such as the TextStream object (line 15 of Listing 19.4). The TextStream object enables you to treat the contents of text files as a very big string of text. Thus, you can avoid having to read the contents of the file a line at a time. Listing 19.4 shows you how to use a TextStream object to read the contents of a text file. Notice that line 21 uses the Read method of the TextStream object ts to read the contents of a text file from within a loop that traverses the entire contents of the TextStream object (lines 20 and 22).
01 Dim fso As New FileSystemObject
02 Dim ts As TextStream
03 Dim strData As String
04
05 `Set a common dialog filter to show only
06 `text files
07 cdlgMain.Filter = "Text (*.txt)|*.txt"
08
09 `Open the common dialog in Show Open mode
10 cdlgMain.ShowOpen
11 gf_strOpenFile = cdlgMain.FileName
12
13 `Get a Text Stream Object using the
14 `OpenTextFile method of the FileSystemObject
15 Set ts = fso.OpenTextFile(gf_strOpenFile)
16
17 `Traverse to the end of the TextStream
18 `concatenating the contents onto a string
19 `buffer variable.
20 Do While ts.AtEndOfStream <> True
21 strData = strData & ts.Read(1)
22 Loop
23
24 `Close the TextStream
25 ts.Close
26
27 `Assign the contents of the string buffer
28 `to the Text property of a TextBox.
29 txtData.Text = strData
You can use the CreateTextFile() method of the FileSystemObject to create a file. Then you can use the Write method of the TextStream object to write data to that created file. Listing 19.5 shows you the code to do this. Notice the Write method is at line 15.
01 `Set a common dialog filter for text
02 cdlgMain.Filter = "Text (*.txt)|*.txt"
03 `Open a save dialog
04 cdlgMain.ShowSave
05 `Get a filename for saving the data
06 gf_strOpenFile = cdlgMain.FileName
07 `Create a TextStream objet to the
08 `filename
09 Set ts = fso.CreateTextFile(gf_strOpenFile, True)
11 `Get the text to write to the file from
12 `the Text property of the TextBox
13 strData = txtData.Text
14 `Do the write
15 ts.Write (strData)
16 `Close the TextSteam
17 ts.Close
In addition to using the file system objects to manipulate files and data, you can query properties of the objects to get information. Listing 19.6 shows you how to use various properties of the File object file to report statistics about a file. Figure 19.6 shows you the result of the code.
01 Dim fso As New FileSystemObject
02 Dim fil As File
03 Dim strData As String
04
05 `Get a file by using the global variable filename
06 Set fil = fso.GetFile(gf_strOpenFile)
07 `Get the filename
08 strData = "Name: " & fil.Name & vbCrLf
09 `Get the date created
10 strData = strData & "Created: " & fil.DateCreated _
& vbCrLf
11 `Get the date last modified
12 strData = strData & "Modifed: " _
& fil.DateLastModified & vbCrLf
13 `Get the date last accessed
14 strData = strData & "Last Access: " _
& fil.DateLastAccessed & vbCrLf
15 `Get the size in bytes
16 strData = strData & "Size: " & CStr(fil.Size) & _
" characters" & vbCrLf
17 `Get the file type
18 strData = strData & "Type: " & fil.Type & vbCrLf
19 `Get the parent folder
20 strData = strData & "Parent: " _
& fil.ParentFolder.Name & vbCrLf
21 `Get the file path
22 strData = strData & "Path: " & fil.Path & vbCrLf
23 `Report the findings
24 MsgBox strData, vbOKCancel, "File Statistics"
FIGURE 19.6 Use the various properties of the File object to obtain information about a file.
The file system objects make coding a computer's file system easier over the long term. In the beginning, however, becoming accustomed to them might seem difficult. The sample project prjFSObj.vbp that you can download shows you how to open a file for reading and writing with file system objects. The code also shows how to create files and obtain file statistics. The code in Listings 19.4 through 19.6 comes from that code. You also might find it useful to take an in-depth look at the File System Object model on the Help files that accompany your copy of VB6. File system objects are powerful, but they take time to master. You will find it time well spent.
© Copyright, Macmillan Computer Publishing. All rights reserved.