Saturday, December 26, 2009

File Operation

Print #N, [variable list]
This statement will write one line of information to the file, that line containing the variables specified in the variable list. (If the variable list is omitted, a blank line will be printed.) If the variables in the list are separated with semicolons (;), they are printed with a single space between them in the file. If separated by commas (,), they are spaced in wide columns. Be careful using the Print statement with string variables. The Print statement does not enclose string variables in quotes, hence, when you read such a variable back in, Visual Basic may have trouble knowing where a string ends and begins. It’s good practice to ‘tack on’ quotes to string variables when using Print.
Example
Dim A As Integer, B As String, C As Single, D As Integer
.
.
Open TestOut For Output As #1
Print #1, A; Chr(34) + B + Chr(34), C
Print #1, D
Close 1
After this code runs, the file TestOut will have two lines. The first will have the variables A, B, and C, delimited by spaces. B will be enclosed by quotes [Chr(34)]. The second line will simply have the value of the variable D.
Quick Example: Writing Variables to Sequential Files
1. Start a new project.
2. Attach the following code to the Form_Load procedure. This code simply writes a few variables to sequential files.

Private Sub Form_Load()
Dim A As Integer, B As String, C As Single, D As Integer
A = 5
B = "Visual Basic"
C = 2.15
D = -20
Open "Test1.Txt" For Output As #1
Open "Test2.Txt" For Output As #2
Write #1, A, B, C
Write #1, D
Print #2, A, B, C
Print #2, D
Close 1
Close 2
End Sub
3. Run the program. Use a text editor (try the Windows 95 Notepad) to examine the contents of the two files, Test1.Txt and Test2.Txt. They are probably in the Visual Basic main directory. Note the difference in the two files, especially how the variables are delimited and the fact that the string variable is not enclosed in quotes in Test2.Txt. Save the application, if you want to.
To read variables from a sequential file, we essentially reverse the write procedure. First, open the file using:

Open SeqFileName For Input As #N

where N is an integer file number and SeqFileName is a complete file path. The file is closed using:

Close N

• The Input statement is used to read in variables from a sequential file. The format is:

Input #N, [variable list]

The variable names in the list are separated by commas. If no variables are listed, the current line in the file N is skipped.

• Note variables must be read in exactly the same manner as they were written. So, using our previous example with the variables A, B, C, and D, the appropriate statements are:

Input #1, A, B, C
Input #1, D

These two lines read the variables A, B, and C from the first line in the file and D from the second line. It doesn’t matter whether the data was originally written to the file using Write or Print (i.e. commas are ignored).

Quick Example: Reading Variables from Sequential Files
1. Start a new project or simply modify the previous quick example.
2. Attach the following code to the Form_Load procedure. This code reads in files created in the last quick example.

Private Sub Form_Load()
Dim A As Integer, B As String, C As Single, D As Integer
Open "Test1.Txt" For Input As #1
Input #1, A, B, C
Debug.Print "A="; A
Debug.Print "B="; B
Debug.Print "C="; C
Input #1, D
Debug.Print "D="; D
Close 1
End Sub

Note the Debug.Print statements and how you can add some identifiers (in quotes) for printed information.
3. Run the program. Look in the debug window and note the variable values. Save the application, if you want to.
4. Rerun the program using Test2.Txt as in the input file. What differences do you see? Do you see the problem with using Print and string variables? Because of this problem, I almost always use Write (instead of Print) for saving variable information to files. Edit the Test2.Txt file (in Notepad), putting quotes around the words Visual Basic. Rerun the program using this file as input - it should work fine now
5. *****************************************************************

In many applications, we would like to be able to save text information and retrieve it for later reference. This information could be a text file created by an application or the contents of a Visual Basic text box.
• Writing Text Files:
To write a sequential text file, we follow the simple procedure: open the file, write the file, close the file. If the file is a line-by-line text file, each line of the file is written to disk using a single Print statement:
Print #N, Line
where Line is the current line (a text string). This statement should be in a loop that encompasses all lines of the file. You must know the number of lines in your file, beforehand.
If we want to write the contents of the Text property of a text box named txtExample to a file, we use:
Print #N, txtExample.Text
Example
We have a text box named txtExample. We want to save the contents of the Text property of that box in a file named MyText.ned on the c: drive in the \MyFiles directory. The code to do this is:
Open “c:\MyFiles\MyText.ned” For Output As #1
Print #1, txtExample.Text
Close 1
The text is now saved in the file for later retrieval.
• Reading Text Files:
To read the contents of a previously-saved text file, we follow similar steps to the writing process: open the file, read the file, close the file. If the file is a text file, we read each individual line with the Line Input command:
Line Input #1, Line
This line is usually placed in a Do/Loop structure that is repeated untill all lines of the file are read in. The EOF() function can be used to detect an end-of-file condition, if you don’t know, a prioiri, how many lines are in the file.
To place the contents of a file opened with number N into the Text property of a text box named txtExample we use the Input function:
txtExample.Text = Input(LOF(N), N)
This Input function has two arguments: LOF(N), the length of the file opened as N and N, the file number.
Example
We have a file named MyText.ned stored on the c: drive in the \MyFiles directory. We want to read that text file into the text property of a text box named txtExample. The code to do this is:

Open “c:\MyFiles\MyText.ned” For Input As #1
txtExample.Text = Input(LOF(1), 1)
Close 1

The text in the file will now be displayed in the text box.
Note that to access a particular data item in a sequential file, you need to read in all items in the file prior to the item of interest. This works acceptably well for small data files of unstructured data, but for large, structured files, this process is time-consuming and wasteful. Sometimes, we need to access data in nonsequential ways. Files which allow nonsequential access are random access files.
• To allow nonsequential access to information, a random access file has a very definite structure. A random access file is made up of a number of records, each record having the same length (measured in bytes). Hence, by knowing the length of each record, we can easily determine (or the computer can) where each record begins. The first record in a random access file is Record 1, not 0 as used in Visual Basic arrays. Each record is usually a set of variables, of different types, describing some item.

A good analogy to illustrate the differences between sequential files and random access files are cassette music tapes and compact discs. To hear a song on a tape (a sequential device), you must go past all songs prior to your selection. To hear a song on a CD (a random access device), you simply go directly to the desired selection. One difference here though is we require all of our random access records to be the same length - not a good choice on CD’s!
• To write and read random access files, we must know the record length in bytes. Some variable types and their length in bytes are:


Type Length (Bytes)
Integer 2
Long 4
Single 4
Double 8
String 1 byte per character
So, for every variable that is in a file’s record, we need to add up the individual variable length’s to obtain the total record length. To ease this task, we introduce the idea of user-defined variables.
Data used with random access files is most often stored in user-defined variables. These data types group variables of different types into one assembly with a single, user-defined type associated with the group. Such types significantly simplify the use of random access files.
• The Visual Basic keyword Type signals the beginning of a user-defined type declaration and the words End Type signal the end. An example best illustrates establishing a user-defined variable. Say we want to use a variable that describes people by their name, their city, their height, and their weight. We would define a variable of Type Person as follows:
Type Person
Name As String
City As String
Height As Integer
Weight As Integer
End Type
These variable declarations go in the same code areas as normal variable declarations, depending on desired scope. At this point, we have not reserved any storage for the data. We have simply described to Visual Basic the layout of the data.


• To create variables with this newly defined type, we employ the usual Dim statement. For our Person example, we would use:
Dim Lou As Person
Dim John As Person
Dim Mary As Person
And now, we have three variables, each containing all the components of the variable type Person. To refer to a single component within a user-defined type, we use the dot-notation:
VarName.Component
As an example, to obtain Lou’s Age, we use:
Dim AgeValue as Integer
.
.
AgeValue = Lou.Age
Note the similarity to dot-notation we’ve been using to set properties of various Visual Basic tools.
We look at writing and reading random access files using a user-defined variable. For other variable types, refer to Visual Basic on-line help. To open a random access file named RanFileName, use:
Open RanFileName For Random As #N Len = RecordLength
where N is an available file number and RecordLength is the length of each record. Note you don’t have to specify an input or output mode. With random access files, as long as they’re open, you can write or read to them.
• To close a random access file, use:
Close N
• As mentioned previously, the record length is the sum of the lengths of all variables that make up a record. A problem arises with String type variables. You don’t know their lengths ahead of time. To solve this problem, Visual Basic lets you declare fixed lengths for strings. This allows you to determine record length. If we have a string variable named StrExample we want to limit to 14 characters, we use the declaration:
Dim StrExample As String * 14
Recall each character in a string uses 1 byte, so the length of such a variable is 14 bytes.
• Recall our example user-defined variable type, Person. Let’s revisit it, now with restricted string lengths:
Type Person
Name As String * 40
City As String * 35
Height As Integer
Weight As Integer
End Type
The record length for this variable type is 79 bytes (40 + 35 +2 + 2). To open a file named PersonData as File #1, with such records, we would use the statement:
Open PersonData For Random As #1 Len = 79
• The Get and Put statements are used to read from and write to random access files, respectively. These statements read or write one record at a time. The syntax for these statements is simple:
Get #N, [RecordNumber], variable
Put #N, [RecordNumber], variable
The Get statement reads from the file and stores data in the variable, whereas the Put statement writes the contents of the specified variable to the file. In each case, you can optionally specifiy the record number. If you do not specify a record number, the next sequential position is used.
• The variable argument in the Get and Put statements is usually a single user-defined variable. Once read in, you obtain the component parts of this variable using dot-notation. Prior to writing a user-defined variable to a random access file, you ‘load’ the component parts using the same dot-notation.
• There’s a lot more to using random access files; we’ve only looked at the basics. Refer to your Visual Basic documentation and on-line help for further information. In particular, you need to do a little cute programming when deleting records from a random access file or when ‘resorting’ records.
Note to both write and read sequential and random access files, we need a file name for the Open statement. To ensure accuracy and completeness, it is suggested that common dialog boxes be used to get this file name information from the user. I’ll provide you with a couple of code segments that do just that. Both segments assume you have a common dialog box on your form named cdlFiles, with the CancelError property set equal to True. With this property True, an error is generated by Visual Basic when the user presses the Cancel button in the dialog box. By trapping this error, it allows an elegant exit from the dialog box when canceling the operation is desired.
•The code segment to obtain a file name (MyFileName with default extension Ext) for opening a file to read is:
Dim MyFileName As String, Ext As String
.
.
cdlFiles.Filter = "Files (*." + Ext + ")|*." + Ext
cdlFiles.DefaultExt = Ext
cdlFiles.DialogTitle = "Open File"
cdlFiles.Flags = cdlOFNFileMustExist + cdlOFNPathMustExist
On Error GoTo No_Open
cdlFiles.ShowOpen
MyFileName = cdlFiles.filename
.
.
Exit Sub
No_Open:
Resume ExitLIne
ExitLine:
Exit Sub
End Sub
A few words on what’s going on here. First, some properties are set such that only files with Ext (a three letter string variable) extensions are displayed (Filter property), the default extension is Ext (DefaultExt property), the title bar is set (DialogTitle property), and some Flags are set to insure the file and path exist (see Appendix II for more common dialog flags).
Error trapping is enabled to trap the Cancel button. Finally, the common dialog box is displayed and the filename property returns with the desired name. That name is put in the string variable MyFileName. What you do after obtaining the file name depends on what type of file you are dealing with. For sequential files, you would open the file, read in the information, and close the file. For random access files, we just open the file here. Reading and writing to/from the file would be handled elsewhere in your coding.
•The code segment to retrieve a file name (MyFileName) for writing a file is:
Dim MyFileName As String, Ext As String
.
.
cdlFiles.Filter = "Files (*." + Ext + ")|*." + Ext
cdlFiles.DefaultExt = Ext
cdlFiles.DialogTitle = "Save File"
cdlFiles.Flags = cdlOFNOverwritePrompt + cdlOFNPathMustExist
On Error GoTo No_Save
cdlFiles.ShowSave
MyFileName = cdlFiles.filename
.
.
Exit Sub
No_Save:
Resume ExitLine
ExitLine:
Exit Sub
End Sub
Note this code is essentially the same used for an Open file name. The Flags property differs slightly. The user is prompted if a previously saved file is selected for overwrite. After obtaining a valid file name for a sequential file, we would open the file for output, write the file, and close it. For a random access file, things are trickier.

No comments:

Post a Comment