VB6 - FILES (Processing a random "file of records") Write, read, re-write to a Direct (Random) file of records. See also READ, WRITE for simple files. Module: modFile Public Type empRecord ' Define user-defined type. ID As Integer Name As String * 20 End Type Form: frmFile Private Sub cmdClear_Click() List1.Clear End Sub Private Sub cmdMakeFile_Click() ' Declare variables. Dim myRecord As empRecord Dim RecordNumber As Integer ' Open file for random access. Open "c:\TESTFILE.txt" For Random _ As #1 Len = Len(myRecord) 'Put some dummy data into the file For RecordNumber = 1 To 7 ' Loop 7 times. myRecord.ID = RecordNumber ' Define ID. myRecord.Name = "MyName" & _ RecordNumber ' Create a string. ' Write record to file. Put #1, RecordNumber, myRecord ' Show the record into the listbox List1.AddItem myRecord.ID & " " & _ myRecord.Name Next RecordNumber Close #1 ' Close file. End Sub Private Sub cmdRandomRead_Click() On Error GoTo Problems Dim myRecord As empRecord Position = Val(txtPosition) If Position > LOF(1) / Len(myRecord) Then GoTo Problems End If Get #1, Position, myRecord ' Read third record. txtName = myRecord.Name GoTo Adios Problems: MsgBox "Bad Index - try Again" Adios: End Sub Private Sub cmdReadFile_Click() ' Declare variables. Dim myRecord As empRecord Dim Position, totalRecords, bytesFile, bytesRecord ' Open sample file for random access. Open "c:\TESTFILE.txt" For Random _ As #1 Len = Len(myRecord) 'find out how many records are there in file #1 bytesFile = LOF(1) bytesRecord = Len(myRecord) totalRecords = bytesFile / bytesRecord ' read data (randomly)from last to first rec. For Position = totalRecords To 1 Step -1 ' Read the sample file using the Get. Get #1, Position, myRecord ' Read the record ' Show the record into the listbox List1.AddItem myRecord.ID & " " & _ myRecord.Name Next 'Close #1 ' Close the active file. End Sub Private Sub Form_Load() On Error GoTo Adios 'delete any previous version of the file Kill "c:\TESTFILE.txt" Adios: End Sub VB.NET version empRecord Class Public Structure empRecord ' Define user-defined type. Dim ID As Short <VBFixedString(30)> Dim Name As String End Structure frmFile Class (GIU) Private Sub cmdClear_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles cmdClear.Click List1.Items.Clear() End Sub Private Sub cmdMakeFile_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles cmdMakeFile.Click ' Declare variables. Dim myRecord As empRecord Dim RecordNumber As Short Dim recLen As Integer ' Open file for random access. recLen = Len(myRecord) FileOpen(1, "c:\TESTFILE.txt", OpenMode.Random, OpenAccess.Write, OpenShare.LockWrite, recLen) 'Put some dummy data into the file For RecordNumber = 1 To 7 ' Loop 7 times. ' Define ID. myRecord.ID = RecordNumber ' Create a string. myRecord.Name = "Data-Employee-" & RecordNumber ' Write record to file. FilePut(1, myRecord, RecordNumber) ' Show the record into the listbox List1.Items.Add(myRecord.ID & _ " " & myRecord.Name) Next RecordNumber FileClose(1) ' Close file. 'enable the other command buttons cmdReadFile.Enabled = True Me.cmdRandomRead.Enabled = True End Sub Private Sub cmdRandomRead_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles cmdRandomRead.Click Dim myRecord As empRecord Dim Position As Short Dim fileNum As Integer ' Open file (if needed) for random access. On Error Resume Next fileNum = FreeFile() FileOpen(fileNum, "c:\TESTFILE.txt", OpenMode.Random, , , Len(myRecord)) On Error GoTo Problems Position = Val(txtPosition.Text) If Position > LOF(fileNum) / Len(myRecord) Then GoTo Problems End If FileGet(fileNum, myRecord, Position) txtName.Text = myRecord.Name GoTo Adios Problems: MsgBox("Bad Index - try Again") Adios: FileClose(fileNum) End Sub Private Sub cmdReadFile_Click(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles cmdReadFile.Click ' Declare variables. Dim myRecord As empRecord Dim bytesFile, Position, As Short Dim totalRecords, recLen As Short Dim fileNum As Integer ' Open sample file for random access. fileNum = FreeFile() recLen = Len(myRecord) FileOpen(fileNum, "c:\TESTFILE.txt", OpenMode.Random, , , recLen) 'find out how many records are there in file #1 bytesFile = LOF(fileNum) totalRecords = bytesFile / recLen ' read data from last rec. to first rec. For Position = totalRecords To 1 Step -1 FileGet(fileNum, myRecord, Position) ' Show the record into the listbox List1.Items.Add(myRecord.ID & " " & myRecord.Name) Next FileClose(fileNum) ' Close file. End Sub Private Sub frmFile_Load(ByVal eventSender As System.Object, ByVal eventArgs As System.EventArgs) Handles MyBase.Load On Error GoTo Adios Kill("c:\TESTFILE.txt") Adios: End Sub VB6 Syntax. GET / PUT STATEMENT Reads/Writes data from/to an open disk file into/from a variable. Syntax Get [#]filenumber, [recnumber], varname Put [#]filenumber, [recnumber], varname The Get/Put statement syntax has these parts: Part filenumber recnumber varname Description Required. Any valid file number. Optional. Variant (Long). Record number (Random mode files) or byte number (Binary mode files) at which reading begins. Required. Valid variable name into which data is read. Remarks Data read with Get is usually written to a file with Put. The first record or byte in a file is at position 1, the second record or byte is at position 2, and so on. If you omit recnumber, the next record or byte following the last Get or Put statement (or pointed to by the last Seek function) is read. You must include delimiting commas, for example: Get #4,,FileBuffer Put #4,,FileBuffer OPEN FILE STATEMENT OPEN enables input/output (I/O) to a file. Syntax Open pathname For mode [Access access] [lock] As [#]filenumber [Len=reclength] The Open statement syntax has these parts: Part Description pathname Required. String expression that specifies a file name¾may include directory or folder, and drive. mode Required. Keyword specifying the file mode: Append, Binary, Input, Output, or Random. If unspecified, the file is opened for Random access. access Optional. Keyword specifying the operations permitted on the open file: Read, Write, or Read Write. lock Optional. Keyword specifying the operations permitted on the open file by other processes: Shared, Lock Read, Lock Write, and Lock Read Write. filenumber Required. A valid file number in the range 1 to 511, inclusive. Use the FreeFile function to obtain the next available file number. reclength Optional. Number less than or equal to 32,767 (bytes). For files opened for random access, this value is the record length. For sequential files, this value is the number of characters buffered. V. Matos - Input/Output VB.NET Page 3 These excerpts are taken from the ©Microsoft .NET Help Facility. Visual Basic .NET I/O File Access Types, Functions, and Statements By itself, a file is nothing more than a series of related bytes of data on a disk. When your application accesses a file, it must assume whether the bytes represent characters, data records, integers, strings, and so on. You tell your application what to assume by specifying the file's access type. The file access type you use depends on what kind of data the file contains. Visual Basic provides three types of file access: Sequential, for reading and writing text files in continuous blocks. Random, for reading and writing text or binary files structured as fixed-length records. Binary, for reading and writing arbitrarily structured files. Sequential access is designed for use with plain text files. Each character in the file is assumed to represent either a text character or a text-formatting sequence, such as a newline character. Data is stored as ANSI characters. A file opened for random access is assumed to be composed of a set of identical-length records, or sets of fields containing information. You can employ user-defined types to create records made up of numerous fields, each of which can have different data types. Data is stored as binary information. Binary access allows you to use files to store data in any form that suits your needs, whether it is numeric, string, or both. Binary access is similar to random access except that no assumptions are made about data type or record length. However, you must know precisely how the data was written to the file to retrieve it correctly. For example, if you store a series of names and phone numbers, you need to remember that the first field (the name) is text and the second field (the phone number) is numeric. File Access Functions and Statements The following functions are used with sequential, random, and binary file access. Dir Function FileDateTime Function GetAttr Function Seek Function EOF Function FileLen Function Loc Function SetAttr Function FileCopy Function FreeFile Function LOF Function Working with large amounts of data often requires that data be written to or read from a file. Before either operation can take place, however, the file must first be opened. The FileOpen Function lets you create and access files with one of three types of file access: Sequential access (Input, Output, and Append modes) is used for writing text files, such as error logs and reports. Random access (Random mode) is used to read and write data to a file without closing it. Random-access files keep data in records, which makes it easy to locate information quickly. Binary access (Binary mode) is used to read or write to any byte position in a file, such as storing or displaying a bitmap image. Do not use the FileOpen function to manipulate files that are usually edited by a specific application, such as Microsoft Office documents or registry files. Doing so will cause file corruption and loss of file integrity. V. Matos - Input/Output VB.NET Page 4 The following table shows the statements typically used when writing data to and reading it from files. Access type Sequential Writing data Print, PrintLine Functions Reading data InputString Function Random FilePut Function FileGet Function Binary FilePut Function FileGet Function FileOpen Function Opens a file for input or output. Public Sub FileOpen( _ ByVal FileNumber As Integer, _ ByVal FileName As String, _ ByVal Mode As OpenMode, _ Optional ByVal Access As OpenAccess = OpenAccess.Default, _ Optional ByVal Share As OpenShare = OpenShare.Default, _ Optional ByVal RecordLength As Integer = -1 _ ) Parameters FileNumber Required. Any valid file number. Use the FreeFile function to obtain the next available file number. FileName Required. String expression that specifies a file name — may include directory or folder, and drive. Mode Required. Enum specifying the file mode: Append, Binary, Input, Output, or Random. Access Optional. Keyword specifying the operations permitted on the open file: Read, Write, or ReadWrite. Defaults to ReadWrite. Share Optional. Enum specifying the operations restricted on the open file by other processes: Shared, Lock Read, Lock Write, and Lock Read Write. Defaults to Shared. RecordLength Optional. Number less than or equal to 32,767 (bytes). For files opened for random access, this value is the record length. For sequential files, this value is the number of characters buffered. Exceptions/Errors Exception type ArgumentException ArgumentException ArgumentException ArgumentException ArgumentException IOException IOException Error num. 5 5 5 5 5 52 55 Condition Invalid Access, Share, or Mode. WriteOnly file is opened for Input. ReadOnly file is opened for Output. ReadOnly file is opened for Append. Record length is negative (and not equal to -1). FileNumber is invalid (<-1 or >255), or FileNumber is already in use. FileName is already open, or FileName is invalid. Remarks V. Matos - Input/Output VB.NET Page 5 You must open a file before any I/O operation can be performed on it. FileOpen allocates a buffer for I/O to the file and determines the mode of access to use with the buffer. If the file specified by FileName doesn't exist, it is created when a file is opened for Append, Binary, Output, or Random modes. The channel to open can be found using the FreeFile() function. Example This example illustrates various uses of the FileOpen function to enable input and output to a file. The following code opens the file TESTFILE in Input mode. FileOpen(1, "TESTFILE", OpenMode.Input) ' Close before reopening in another mode. FileClose(1) This example opens the file in Binary mode for writing operations only. FileOpen(1, "TESTFILE", OpenMode.Binary,OpenAccess.Write) ' Close before reopening in another mode. FileClose(1) The following example opens the file in Random mode. The file contains records of the structure Person. Structure Person <VBFixedString(30)> Dim Name As String Dim ID As Integer End Structure ' Count 30 for the string, plus 4 for the integer. FileOpen(1, "TESTFILE", OpenMode.Random, , , 34) ' Close before reopening in another mode. FileClose(1) This code example opens the file in Output mode; any process can read or write to file. FileOpen(1, "TESTFILE", OpenMode.Output, OpenShare.Shared) ' Close before reopening in another mode. FileClose(1) This code example opens the file in Binary mode for reading; other processes can't read file. FileOpen(1, "TESTFILE", OpenMode.Binary, OpenAccess.Read, OpenShare.LockRead) V. Matos - Input/Output VB.NET Page 6 Opening Files for Sequential Access Using System.IO is the recommended way to create text files, but should you need to use older text file-creation methods, this section shows you how. Sequential access works best when you want to process files consisting only of text, such as files created with a typical text editor, not files in which data is divided into a series of records. Sequential access is not well suited for storing long series of numbers, because each number is stored as a character string. Thus, a four-digit number would require four bytes of storage instead of the two bytes required to store the same number as an integer. When you open a file for sequential access, you must specify whether to input characters from the file (Input mode), output characters to the file (Output mode), or append characters to the file (Append mode). To open a file for sequential access Use the FileOpen Function with the following syntax: FileOpen(FileNumber, FileName, OpenMode.Input) When you open a sequential file for Input, the file must already exist; otherwise an error occurs. When you try to open a nonexistent file for Output or Append, however, the FileOpen statement creates the file first and then opens it. After opening a file for an Input, Output, or Append operation, you must close it with the FileClose Function statement before reopening it for another type of operation. Editing Files Opened for Sequential Access To edit a file, you must first read its contents to program variables, then change the variables, and finally, write the variables back to the file. The following sections discuss how to edit records opened for sequential access. To read strings from files 1. 2. Retrieve the contents of a text file by opening it for Input. Use the LineInput, InputString, or Input functions to copy the file into program variables. Visual Basic provides statements and functions that read and write sequential files one character at a time or one line at a time. For example, the following code fragment reads a file line by line: Dim LinesFromFile, NextLine As String, FileNum As Integer Do Until EOF(FileNum) LineInput(FileNum, NextLine) LinesFromFile = LinesFromFile & NextLine & Chr(13) & Chr(10) Loop Although the LineInput function recognizes the end of a line when it comes to the carriage return/line feed sequence, it does not include that sequence when it reads the line into the variable. If you want to retain the carriage return/line feed, your code must add it. You can use the InputString function to copy a specified number of characters from a file to a variable, provided the variable is large enough. For example, the following code uses InputString to copy CharCount number of characters to a variable: V. Matos - Input/Output VB.NET Page 7 LinesFromFile = InputString(FileNum, CharCount) You can also use the Input function, which reads a list of numbers and/or string expressions from a file. For example, to read in a line from a mailing list file, you might use the following statements: Input(FileNum, Input(FileNum, Input(FileNum, Input(FileNum, Input(FileNum, Input(FileNum, fname) lname) street) city) state) zip) Writing Strings to Sequential-Access Files You can add data in the form of strings to existing files via the Print Function or in the form of numbers and string expressions through the Write Function. To write strings to files 1. 2. Use the FileOpen Function to open a text file for Output or Append. Use the Print function to write the strings to the file as in the following example, which a text editor might use to copy the contents of a text box into a file: Print(FileNum, TheBox.Text) Visual Basic also supports the Write function, which writes a list of numbers and/or string expressions to a file. It automatically separates each expression with a comma and puts quotation marks around String expressions, as illustrated in the following code: Dim AnyString As String, AnyNumber, FileNum As Integer AnyString = "AnyCharacters" AnyNumber = 23445 Write(FileNum, AnyString, AnyNumber) The previous code segment writes two expressions to the file specified by FileNum. The first contains a string, and the second contains the number 23445. Therefore, Visual Basic writes the following characters (including all punctuation) to the file: "AnyCharacters",23445 Note If you are maintaining a database using Write and Input with sequential access, consider using FilePutObject and FileGetObject with random or binary access instead; both types of access are better suited to record-oriented data. One of the primary differences between Print and Write is that Print formats the string, while Write does not. For this reason, Print does not include quotation marks around the string, which is formatted as the user would like to see it, while Write does. Use a function that writes each string to a new line, such as PrintLine or WriteLine if you need strings separated by line. V. Matos - Input/Output VB.NET Page 8 Random File Access The bytes in random-access files form records of uniform length, each containing one or more fields. A record with one field corresponds to any standard type, such as an integer or fixed-length string. A record with more than one field corresponds to a user-defined type. In this section you declare, open, edit, and write to a random-access file, using a hypothetical Employee Records database as an example. Each file-access aspect of the example is discussed separately in the topics listed immediately below. Declaring Variables for Random File Access Before your application opens a file for random access, it should declare all variables required to handle data from the file. This includes user-defined types, which correspond to records in the file, as well as standard types for other variables that hold data related to processing a random-access file. Before opening a file for random access, define a structure that corresponds to the records the file contains or will contain. For example, a hypothetical Employee Records database might contain a user-defined data type called Person as follows: Structure Person Public ID As Integer Public MonthlySalary As Decimal Public LastReviewDate As Long <VBFixedString(15)> Public FirstName As String <VBFixedString(15)> Public LastName As String <VBFixedString(15)> Public Title As String <VBFixedString(150)> Public ReviewComments As String End Structure Declaring Field Variables in a Structure Definition Because all records in a random-access file must have the same length, it is often useful for string elements in a user-defined type to have a fixed length also. In the Person type declaration above, for example, FirstName and LastName have a fixed length of 15 characters. To declare a fixed-length string, set its length with the VBFixedString attribute. If the actual string contains fewer characters than the fixed length of the string element to which it is written, Visual Basic fills the trailing spaces in the record with blanks (character code 32). If the string is longer than the field size, Visual Basic truncates it. (If you use variable-length strings, the total size of any record stored with the FilePut Function or retrieved with the FileGet Function must not exceed the record length specified in the FileOpen Function). After defining a structure that corresponds to a typical record, declare any other variables that your application needs to process a file opened for random access. The Employee Records database, for instance, declares Employee, Position, and LastRecord variables, as follows: ' Declare a record variable. Public Employee As Person ' Track the current record. Public Position As Long ' Get the number of the last record in the file. Public LastRecord As Long V. Matos - Input/Output VB.NET Page 9 Opening Files for Random Access After you create the file, you need to open it to make any modifications. To open a file for random access Use the FileOpen Function with the following syntax: FileOpen(FileNumber, FileName, OpenMode.Random, , , RecordLength) FileNumber and FileName specify the file number and name of the file to be opened, respectively. RecordLength specifies the size of each record in bytes. If RecordLength is less than the actual length of the record written to the file, an error is generated. If RecordLength is greater than the actual length of the record, the record is written, although some disk space may be wasted. Note that every String variable in Visual Basic stores an ASCII string, and that you must specify the byte length of that ASCII string. In Declaring Variables for Random File Access, a hypothetical Employee Records database first defined a Person data type and then declared a record variable of that type as well as two other variables for processing records. The following code continues the Employee Records example, demonstrating how to open a random-access file to accept Employee data of user-defined type Person: Sub Main() Dim FileNum As Integer, RecLength As Long, Employee As Person ' Calculate the record length. RecLength = Len(Employee) ' Get the next available file number. FileNum = FreeFile ' Open the new file with the FileOpen statement. FileOpen(FileNum, "MYFILE.DAT", OpenMode.Random, , , RecLength) End Sub Editing Files Opened for Random Access To edit a random-access file, first read records from the file into program variables, and then change the values in the variables. In Declaring Variables for Random File Access and Opening Files for Random Access, a hypothetical Employee Records database defined variables for reading and writing employee records. The following step describes how to read and copy employee records using those variables. To read and copy records into variables Use the FileGetObject Method, which copies a record from the Employee Records file into the Employee variable: FileGet(FileNum, Employee, Position) In this line of code, FileNum contains the number that the FileOpen Function used to open the file, Position contains the number of the record to copy, and Employee, declared as the user-defined type Person, receives the contents of the record. Writing Variables to Records After editing records read into program variables from a random-access file, use the FilePut Function to replace or add records. In Declaring Variables for Random File Access and Opening Files for Random Access, a hypothetical Employee Records database defined variables for reading and writing employee records. The following steps describe how to replace and add employee records using those variables. V. Matos - Input/Output VB.NET Page 10 To replace a record Use FilePut to specify the position of the record you want to replace. The Random File Access example illustrates this in the following code: FilePut(FileNum, Employee, Position) This code replaces the record number specified by Position with the data in the Employee variable. To add a record Using FilePut, set the value of the Position variable equal to one more than the number of records in the file. To add a record to a file that contains five records, for example, set Position equal to 6. In the case of the Employee Records example, substituting the following statements for the FilePut statement above adds a record to the end of the file instead of overwriting the one specified by Position: LastRecord = LastRecord + 1 FilePut(FileNum, Employee, LastRecord) Deleting Records You can delete a record's contents by clearing its fields, but the record will still exist in the file. In most cases, you don't want empty records in your file because they waste space. To avoid this, you can copy the remaining records to a new file, and then delete the old one; or, you can make a note of the location of the empty record and use that slot on the next insert operation. To delete a record Clear the record's fields. To remove a deleted record 1. 2. 3. 4. Create a new file. Copy all the valid records from the original file into the new file. Close the original file and use the Kill function to delete it. Use the Rename function to rename the new file with the name of the original file. V. Matos - Input/Output VB.NET Page 11 FileLen Function Returns a Long value specifying the length of a file in bytes. Public Function FileLen(ByVal PathName As String) As Long Parameter PathName Required. String expression that specifies a file. PathName may include the directory or folder, and the drive. Exceptions/Errors Exception type FileNotFoundException Error number 53 Condition File does not exist. Remarks If the specified file is open when the FileLen function is called, the value returned represents the size of the file at the time it was opened. Note To obtain the current length of an open file, use the LOF function. Example This example uses the FileLen function to return the length of a file in bytes. For purposes of this example, assume that TESTFILE is a file containing some data. Dim MySize As Long MySize = FileLen("TESTFILE") ' Returns file length (bytes). V. Matos - Input/Output VB.NET Page 12 LOF Function Returns a Long representing the size, in bytes, of a file opened using the FileOpen function. Public Function LOF(ByVal FileNumber As Integer) As Long Parameter FileNumber Required. An Integer containing a valid file number. Exceptions/Errors Exception type IOException IOException Error number 52 54 Condition FileNumber does not exist. File mode is invalid. Remarks Use the FileLen function to obtain the length of a file that is not open. Example This example uses the LOF function to determine the size of an open file. This example assumes that TESTFILE is a text file containing sample data. Dim length As Integer FileOpen(1, "C:\TESTFILE.TXT", OpenMode.Input) ' Open file. length = LOF(1) ' Get length of file. Debug.WriteLine(length) FileClose(1) ' Close file. V. Matos - Input/Output VB.NET Page 13 Binary File Access Use binary access when it is important to keep file size small. Because binary access doesn't require fixed-length fields, the type declaration can omit the string length parameters. This enables you to conserve disk space by building variable-length records. Opening a File for Binary Access Use binary access when it is important to keep file size small. Because binary access doesn't require fixed-length fields, you can conserve disk space by building variable-length records. To open a file for binary access Use the FileOpen Function with the following syntax: FileOpen(FileNumber, FileName, OpenMode.Binary) As you can see, opening files for binary access differs from Opening Files for Random Access in that the RecordLength expression is not specified. (If you do include a record length in a binary-access FileOpen function, it is ignored.) To appreciate binary access, consider the Employee Records example discussed in the Random File Access section. This random-access file uses fixed-length records and fields to store information about employees. As a result, every record in the Employee Records database takes the same number of bytes, regardless of the actual contents of the fields. You can minimize the size of Employee Records by using binary access. Because you are not required to use fixedlength fields, you can omit the string-length parameters from the type declaration, as in the following code: Structure Person ID As Integer MonthlySalary As Decimal LastReviewDate As Long FirstName As String LastName As String Title As String ReviewComments As String End Structure Public Employee As Person ' Defines a record. Each employee record in the Employee Records file now occupies only the exact number of bytes required, because the fields are of variable lengths. The drawback to binary input/output with variable-length fields is that you cannot randomly access records; you must instead access them sequentially to learn the length of each one. You can still go directly to a specified byte position in a file, but if the fields are of variable length, there is no direct way to know which record is at which byte position. V. Matos - Input/Output VB.NET Page 14 Accessing Files with FileSystemObject The File System Object (FSO) model provides an object-based tool for working with folders and files. It allows you to use the familiar object.method syntax with a rich set of properties, methods, and events to process folders and files. You can also employ the traditional Visual Basic statements and commands. The FSO model gives your application the ability to create, alter, move, and delete folders, or to determine if and where particular folders exist. It also enables you to get information about folders, such as their names and the date they were created or last modified. The FSO model makes processing files much easier as well. When processing files, your primary goal is to store data in an efficient, easy-to-access format. You need to be able to create files, insert and change the data, and output (read) the data. Although you can store data in a database, doing so adds a significant amount of overhead to your application. You may not want to have such overhead, or your data access requirements may not call for the extra functionality associated with a full-featured database. In this case, storing your data in a text file or binary file is the most efficient solution. The FSO model, contained in the Scripting type library (Scrrun.dll), supports the creation and manipulation of text files through the TextStream object; however, the FSO model does not support binary files. To manipulate binary files, use the FileOpen Function with the Binary keyword. The following objects make up the FSO model: Object FileSystemObject Drive Folder File TextStream Description Allows you to create, delete, gain information about, and generally manipulate drives, folders, and files. Many of the methods associated with this object duplicate those in the other objects. Allows you to gather information about a drive attached to the system, such as how much room is available and what its share name is. Note that a "drive" under the FSO model isn't necessarily a hard disk: it can be a CD-ROM drive, a RAM disk, and so forth. A drive also isn't required to be physically attached to the system; it can also be logically connected through a local area network (LAN). Allows you to create, delete, or move folders, as well as query the system about their names, paths, and other information. Allows you to create, delete, or move files, as well as query the system about their names, paths, and other information. Enables you to read and write text files. For information about the various properties, methods, and events in the FSO model, use the Object Browser in Visual Basic by pressing CTRL+ALT+J and looking at the Scripting type library. If the Scripting type library does not appear in the list, create a reference to it as shown in the next section. Programming in the FSO Model Programming in the FSO model entails three main tasks: Creating a FileSystemObject object by using the CreateObject method, or by dimensioning a variable as a FileSystemObject object. Using the appropriate method on the newly created object. Accessing the object's properties. The FSO model is contained in the Scripting type library, which is located in the file Scrrun.dll. If you don't already have a reference to it, you can create one. To create a reference to the Scripting type library (Scrrun.dll) 1. On the Project menu, click Add Reference, and then click the COM tab. V. Matos - Input/Output VB.NET Page 15 2. Choose Microsoft Scripting Runtime from the Component Name list, and then click Select. You can now use the Object Browser to view the FSO model's objects, collections, properties, methods, events, and constants. To create a FileSystemObject object Dimension a variable as type FileSystemObject, as in the following code: Dim fso As New FileSystemObject - or - Use the CreateObject method to create a FileSystemObject object, as in the following code: fso = CreateObject("Scripting.FileSystemObject") In the second example, Scripting is the name of the type library, and FileSystemObject is the name of the object of which you want to create an instance. Note The first method works only in Visual Basic, while the second method works either in Visual Basic or VBScript. FSO Methods The following table shows FSO methods and the tasks that they perform: Task Command Create a new object CreateFolder or CreateTextFile Delete a file or folder DeleteFile or File.Delete; DeleteFolder or Folder.Delete Copy an object CopyFile or File.Copy; CopyFolder or Folder.Copy Move an object MoveFile or File.Move; MoveFolder or Folder.Move Access an existing drive, folder, or file GetDrive, GetFolder, or GetFile Note The FSO model does not support the creation or deletion of drives. As you can see, some functionality in the FileSystemObject object model is redundant. For example, you can copy a file using either the CopyFile method of the FileSystemObject object, or you can use the Copy method of the File object. The methods work the same way; both versions are included to give you maximum programming flexibility. Note, however, that you don't need to use the Get methods for a newly created object, since the Create functions already return a handle to it. For example, if you create a new folder using the CreateFolder method, you don't need to use the GetFolder method to access its properties, such as Name, Path, or Size. Just set a variable to the CreateFolder function to gain a handle to the newly created folder, and then access its properties, methods, and events. Drive Information The Drive object allows you to get information about the various drives attached to a system, either physically or over a network. Its properties contain the following information: Property TotalSize AvailableSpace, FreeSpace DriveLetter DriveType Description Total size of the drive, in bytes How much space is available on the drive, in bytes Letter assigned to the drive Type of drive (removable, fixed, network, CD-ROM, or V. Matos - Input/Output VB.NET Page 16 SerialNumber FileSystem IsReady ShareName, VolumeName Path, RootFolder RAM disk) Drive's serial number Type of file system the drive uses (FAT, FAT32, or NTFS) Whether a drive is available for use Name of the share and/or volume Path or root folder of the drive App.Path, ChDir, ChDrive, and CurDir If you use the Path property (App.Path), the ChDrive and ChDir statements, or the CurDir function, be aware that they may return a Universal Naming Convention (UNC) path (that is, one beginning with \\Server\Share…) rather than a drive path (such as e:\Folder), depending on how you run your program or project. App.Path returns a UNC path when: You run a project after loading it from a network share, even if the network share is mapped to a drive letter. You run a compiled executable file from a network share (but only if it is run using a UNC path). ChDrive cannot handle UNC paths, and it raises an error when App.Path returns one. You can handle this error by adding On Error Resume Next before the ChDrive statement, or by testing the first two characters of App.Path to see if they are backslashes. The command prompt always has a drive path for the current directory, so CurDir is set to a drive path. ChDir does not raise an error, but it fails to change the directory from a drive path to a UNC path. The only workaround for this situation is to locate a local drive that is mapped to the share specified in the UNC path, or to use network commands to create such a mapping. If the project is loaded into the Visual Basic development environment from a network share — either a UNC path or a mapped drive path — App.Path returns a UNC path when the project is run and ChDrive fails and raises an error. ChDir does not raise an error, but it fails to change the directory. The only workaround for this situation is to manually set the drive and directory. If more than one person can open the project on the network share, you can use an MS-DOS environment variable to give each person a customized mapping for the share. Folder Information The following table shows the methods for carrying out common folder tasks: Method FileSystemObject.CreateFolder Folder.Delete or FileSystemObject.DeleteFolder Folder.Move or FileSystemObject.MoveFolder Folder.Copy or FileSystemObject.CopyFolder Folder.Name FileSystemObject.FolderExists FileSystemObject.GetFolder FileSystemObject.GetParentFolderName FileSystemObject.GetSpecialFolder Task Create a folder. Delete a folder. Move a folder. Copy a folder. Retrieve the name of a folder. Find out if a folder exists on a drive. Get an instance of an existing Folder object. Find out the name of a folder's parent folder. Find out the path of a system folder. Sequential Text Files and FSO Sequential text files (sometimes referred to as a text stream) are useful when you want to read the contents of a file within a FileSystemObject object. You can access sequential text files with these methods: V. Matos - Input/Output VB.NET Page 17 Method Task CreateTextFile, OpenTextFile, or OpenAsTextStream Create a sequential text file. Write or WriteLine Add data to a text file. Read, ReadLine, or ReadAll Read data from a text file. File.Move or MoveFile Move a file. File.Copy or CopyFile Copy a file. File.Delete or DeleteFile Delete a file. System.IO Namespace The IO namespace contains types that allow synchronous and asynchronous reading and writing on data streams and files. Namespace hierarchy Classes Class BinaryReader BinaryWriter BufferedStream Directory DirectoryInfo DirectoryNotFoundException EndOfStreamException ErrorEventArgs File FileInfo FileLoadException FileNotFoundException FileStream FileSystemEventArgs FileSystemInfo FileSystemWatcher InternalBufferOverflowException IODescriptionAttribute IOException Description Reads primitive data types as binary values in a specific encoding. Writes primitive types in binary to a stream and supports writing strings in a specific encoding. Reads and writes to another stream. This class cannot be inherited. Exposes static methods for creating, moving, and enumerating through directories and subdirectories. Exposes instance methods for creating, moving, and enumerating through directories and subdirectories. The exception that is thrown when part of a file or directory cannot be found. The exception that is thrown when reading is attempted past the end of a stream. Provides data for the Error event. Provides static methods for the creation, copying, deletion, moving, and opening of files, and aids in the creation of FileStream objects. Provides instance methods for the creation, copying, deletion, moving, and opening of files, and aids in the creation of FileStream objects. The exception that is thrown when a file is found but cannot be loaded. The exception that is thrown when an attempt to access a file that does not exist on disk fails. Exposes a Stream around a file, supporting both synchronous and asynchronous read and write operations. Provides data for the directory events: Changed, Created, Deleted. Provides the base class for both FileInfo and DirectoryInfo objects. Listens to the file system change notifications and raises events when a directory, or file in a directory, changes. The exception thrown when the internal buffer overflows. Sets the description visual designers can display when referencing an event, extender, or property. The exception that is thrown when an I/O error occurs. V. Matos - Input/Output VB.NET Page 18 MemoryStream Path Creates a stream whose backing store is memory. Performs operations on String instances that contain file or directory path information. These operations are performed in a cross-platform manner. The exception that is thrown when a pathname or filename is longer than the system-defined maximum length . Provides data for the Renamed event. Provides a generic view of a sequence of bytes. Implements a TextReader that reads characters from a byte stream in a particular encoding. Implements a TextWriter for writing characters to a stream in a particular encoding. Implements a TextReader that reads from a string. Writes information to a string. The information is stored in an underlying StringBuilder. Represents a reader that can read a sequential series of characters. Represents a writer that can write a sequential series of characters. This class is abstract. PathTooLongException RenamedEventArgs Stream StreamReader StreamWriter StringReader StringWriter TextReader TextWriter Structures Structure WaitForChangedResult Description Contains information on the change that occurred. Delegates Delegate ErrorEventHandler FileSystemEventHandler RenamedEventHandler Description Represents the method that will handle the Error event of a FileSystemWatcher. Represents the method that will handle the Changed, Created, or Deleted event of a FileSystemWatcher class. Represents the method that will handle the Renamed event of a FileSystemWatcher class. Enumerations Enumeration FileAccess FileAttributes FileMode FileShare NotifyFilters SeekOrigin WatcherChangeTypes Description Defines constants for read, write, or read/write access to a file. Provides attributes for files and directories. Specifies how the operating system should open a file. Contains constants for controlling the kind of access other FileStreams can have to the same file. Specifies changes to watch for in a file or folder. Provides the fields that represent reference points in streams for seeking. Changes that may occur to a file or directory. V. Matos - Input/Output VB.NET Page 19 FileStream Members Public Constructors FileStream Constructor Overloaded. Initializes a new instance of the FileStream class. Public Properties CanRead CanSeek CanWrite Handle IsAsync Overridden. Gets a value indicating whether the current stream supports reading. Overridden. Gets a value indicating whether the current stream supports seeking. Overridden. Gets a value indicating whether the current stream supports writing. Gets the operating system file handle for the file that the current FileStream object encapsulates. Gets a value indicating whether the FileStream was opened asynchronously or synchronously. Overridden. Gets the length in bytes of the stream. Length Name Position Gets the name of the FileStream that was passed to the constructor. Overridden. Gets or sets the current position of this stream. Public Methods Overridden. Begins an asynchronous read. BeginRead Overridden. Begins an asynchronous write. BeginWrite Close CreateObjRef (inherited from MarshalByRefObject) EndRead EndWrite Equals (inherited from Object) Flush GetHashCode (inherited from Object) Overridden. Closes the file and releases any resources associated with the current file stream. Creates an object that contains all the relevant information required to generate a proxy used to communicate with a remote object. Overridden. Waits for the pending asynchronous read to complete. Overridden. Ends an asynchronous write, blocking until the I/O operation has completed. Overloaded. Determines whether two Object instances are equal. Overridden. Clears all buffers for this stream and causes any buffered data to be written to the underlying device. Serves as a hash function for a particular type, suitable for use in hashing algorithms and data structures like a V. Matos - Input/Output VB.NET Page 20 GetLifetimeService (inherited from MarshalByRefObject) hash table. Retrieves the current lifetime service object that controls the lifetime policy for this instance. Gets the Type of the current instance. GetType (inherited from Object) InitializeLifetimeService (inherited from MarshalByRefObject) Obtains a lifetime service object to control the lifetime policy for this instance. Prevents access by other processes to all or part of a file. Lock Read ReadByte Seek SetLength Overridden. Reads a block of bytes from the stream and writes the data in a given buffer. Overridden. Reads a byte from the file and advances the read position one byte. Overridden. Sets the current position of this stream to the given value. Overridden. Sets the length of this stream to the given value. Returns a String that represents the current Object. ToString (inherited from Object) Unlock Write WriteByte Allows access by other processes to all or part of a file that was previously locked. Overridden. Writes a block of bytes to this stream using data from a buffer. Overridden. Writes a byte to the current position in the file stream. Protected Methods Allocates a WaitHandle object. CreateWaitHandle (inherited from Stream) Dispose Finalize Releases the unmanaged resources used by the FileStream and optionally releases the managed resources. Overridden. Ensures that resources are freed and other cleanup operations are performed when the garbage collector reclaims the FileStream. In C# and C++, finalizers are expressed using destructor syntax. Creates a shallow copy of the current Object. MemberwiseClone (inherited from Object) V. Matos - Input/Output VB.NET Page 21