简介
有经验的 Visual Basic 开发人员最初可能会认为,Visual Basic .net 中的变化使本来已经熟悉的领域变得陌生而难以驾驭。其实,过去开发的成果仍然可以使用。例如,Visual Basic 运行时文件 I/O 方法就是大家比较熟悉的。同样,以前曾涉猎过 FileSystemObject 对象的开发人员也可以继续在这一领域畅游。尽管公共语言运行时领域可能让人感到陌生并且到处都是以对象为中心的“怪物”,但同时,它提供的功能却极具诱惑力,例如 FileSystemWatcher 或 FileIOPermissions 类中的新功能。
事实上,唯一让 Visual Basic .NET 开发人员望而却步的是如何从这三种方法中进行选择。对许多应用程序而言,对文件和目录进行操作是最重要的,但是 Visual Basic .NET 所提供的灵活方法可能会使人感到困惑,并且会提出下列问题:Visual Basic .NET 提供什么样的文件访问?何时使用 FileSystemObject 对象?使用公共语言运行时中的方法有哪些好处?是否需要专门使用一种方法?如何选择方法?
Visual Basic .NET 中的文件方法
让我们先看看 Microsoft.VisualBasic 命名空间,这可以为那些被全新的 .NET 领域吓坏的开发人员带来一些安慰和信心。命名空间包含许多熟悉的函数和方法。除了部分名称有少许改动外,大部分名称仍保持不变,如 Dir、Input、Print、Seek、Write 等等。
在选择运行时函数时,主要应考虑写入文件或从文件中收集的信息的类型。Visual Basic .NET 为三种类型的文件提供了访问方法,每种方法适用于一种特定的数据类型:二进制、顺序和随机。
二进制访问,允许您以任意方式存储和访问数据,这种方法对于变长字段尤为有用。
随机访问,允许您以记录的方式存储和访问信息,这种方法假定记录是等长的。顺序访问,允许您在文本文件中读取和写入字符串。
这些不同类型的文件访问所使用的函数发生了一些变化。最显著的变化是用 FilePut/FilePutObject 和 FileGet/FileGetObject 函数代替 Put 和 Get 函数。在 Visual Basic .NET 中,FilePut 和 FileGet 映射到 Put 和 Get 函数;FilePutObject 和 FileGetObject 用于将 Object 类型(等价于 Visual Basic 早期版本中的 Variant 类型)的对象写入文件。
例如,下面是 Visual Basic 6.0 的代码:
Dim Person As Variant
If IdentifyPeopleByName Then
Person = "我的姓名 1"
Else
Person = 564
EndIf
Put #1, , Person
在 Visual Basic .NET 中变为:
FileOpen(1, "c:\test.txt", OpenMode.Binary)
Dim Person As Object
If IdentifyPeopleByName Then
Person = "我的姓名 1"
Else
Person = 564
EndIf
FilePutObject(1, Person)
FileClose(1)
总之,对于有经验的 Visual Basic 程序员来说,这一方面应该很容易掌握。下表列出了 Visual Basic .NET 中用于文件和目录操作的函数,并提供了介绍各个函数的相应主题的链接。
函数
说明
CurDir
返回表示当前目录的 String 值。
Dir
返回 String 值,表示与指定模式或文件属性相匹配的文件名、目录名或文件夹名,或者表示驱动器的卷标。
EOF
当为随机输入或顺序输入而打开的文件到达末尾时,返回 Boolean 值 True。
FileClose
将 I/O 写入到使用 FileOpen 函数打开的文件。
FileCopy
复制文件并保留原文件。
FileDateTime
返回 Date 值,表明最近一次修改文件的日期和时间。
FileLen
返回 Long 值,表明文件的长度(字节)。
FileOpen
打开用于输入或输出的文件。
FreeFile
返回 Integer 值,指定 FileOpen 函数可以使用的下一个文件的编号。
GetAttr
返回 FileAttribute 值,表示文件、文件夹或目录的属性。
Input
从打开的顺序文件读取数据并将该数据分配给变量。
InputString
返回 String 值,包含在 Input 或 Binary 模式下打开的文件中的字符。
LineInput
从打开的顺序文件中读取一行并将其分配给 String 变量。
Loc
返回 Long 值,指定在打开的文件中的当前读/写位置。
LOF
返回 Long 值,表示使用 FileOpen 函数打开的文件的大小(字节)。
将显示格式的数据写入顺序文件。
PrintLine
将显示格式的数据写入顺序文件,并以回车符结束。
Seek
返回 Long 值,指定在使用 FileOpen 函数打开的文件中的当前读/写位置;或为使用 FileOpen 函数打开的文件中的下一个读/写操作设置位置。
SetAttr
设置文件的属性信息,如 ReadOnly、Hidden、Directory、Archive 等等。
Write
将数据写入顺序文件。通常使用 Input 函数从文件中读取使用 Write 函数写入的数据。
WriteLine
将数据写入顺序文件,并以回车符结束。
优点和缺点
Visual Basic .NET 运行时提供的函数有两个主要优点,即为开发人员所熟悉并且易于使用。Visual Basic .NET 的核心功能仍然保留其为人所熟悉、直观和灵活的特点,同时提供了舒适的 .NET 开发环境。
同样,将在 Visual Basic 早期版本中编写的程序升级到 .NET,或者创建能够与在 Visual Basic 早期版本中编写的应用程序正常交互的应用程序,也相对简单。
Visual Basic .net 函数还提供二进制文件访问,为使用变长字段时提供了更好的选择,而 FileSystemObject 对象(将在下一节介绍)则没有此功能。
最后一点,在从 Visual Basic .NET 中使用 Visual Basic .NET 内置文件 I/O 函数时,没有需要特别注意的事项(如需要导入命名空间)。
Visual Basic .NET 文件 I/O 函数仅支持 String、Date、Integer、Long、Single、Double 和 Decimal 写入类型以及这些类型的结构和数组,这是使用这些函数时的一个缺点。此外,不能将类序列化,因此,在这些情况下直接使用 System.IO 类性能可能会更佳。
代码示例
如以下各例所示,使用 Visual Basic 运行时方法进行文件和目录操作是开发人员所熟悉的。
以下示例将检查文件是否存在,如果存在,则使用 FileCopy 函数将其复制到新文件。
Private Sub CopyFiles()
Dim checkFile As String
checkFile = Dir$("c:\test.txt")
If checkFile = "test.txt"
FileCopy "c:\test.txt", "c:\new.txt"
End If
End Sub
以下示例使用 FilePut 函数将数据写入文件,FilePut 函数与 Visual Basic 早期版本的 Put 函数相对应。结构 CustomerRecord 的三个记录被写入文件。
Structure CustomerRecord
Public OrderNumber As Integer
Public Name As String
Public OrderDate As Date
End Structure
Sub WriteData()
Dim MyRecord As CustomerRecord
Dim RecordNumber As Integer
Dim RecordDate As Date
' 打开文件进行随机访问。
FileOpen(1, "C:\TESTFILE.txt", OpenMode.Binary)
For RecordNumber = 1 To 3 ' 循环 3 次。
MyRecord.OrderNumber = RecordNumber
' 定义 OrderNumber。
MyRecord.OrderDate = RecordDate
' 定义 OrderDate。
MyRecord.Name = "我的姓名" & RecordNumber
' 创建字符串。
FilePut(1, MyRecord)
' 将记录写入文件。
Next RecordNumber
FileClose(1)
End Sub
FileSystemObject
与 Microsoft.VisualBasic 命名空间提供的函数和方法类似,Visual Basic 早期版本的用户也应当熟悉 FileSystemObject 对象。在 Visual Basic .NET 中仍然可以使用此对象。
FileSystemObject (FSO) 模型将文件、目录和驱动器表示为 COM 对象,每个对象都有自己的属性和方法。您可以创建和操纵这些对象,并使用这些对象的属性来查找信息,如目录内容、文件大小、对象的创建时间等等。通过创建和访问 FileSystemObject 对象的实例,可以访问表示系统文件、目录和驱动器的对象。
FSO 对象模型位于 Microsoft 脚本运行时类型库 (Scrrun.dll) 中,支持通过 TextStream 对象创建和操纵文本文件。有关详细信息,请参阅 TextStream。FileStream 类围绕文件提供一个数据流,允许对文件系统进行同步或异步读写操作以及缓冲输入和输出,以改善性能。信息被写入缓冲区,只有当缓冲区已满或调用 Close 方法时,缓冲区中的内容才会被写入文件。
优点和缺点
FSO 的主要优点是,它可以将许多文件 I/O 函数集合到单个对象中。通过创建该对象的实例,可以访问对象的方法和属性。
下表列出了 FSO 对象模型的基本组件,并提供了与相应主题对应的链接,这些主题列出了适用于创建和操纵文件、驱动器及目录的属性和方法。
对象
说明
FileSystemObject
创建与删除驱动器、文件夹和文件,获取其信息并对其进行常规操作。与此对象相关的许多方法都与其他对象中的相应方法相同。
Drive
获取关于连接到系统的驱动器的信息,如可用空间及其共享名称。
File
创建,删除或移动文件,以及在系统中查询文件的名称、路径和其他信息。
Folder
创建,删除或移动文件夹,以及在系统中查询文件夹的名称、路径和其他信息。
TextStream
读写文本文件。
FSO 对象模型也适用于线程。它提供了一个用于异步 I/O 的构造函数,如当使用 BeginRead 和 BeginWrite 方法时,该函数可使主线程继续,允许用户稍后再处理数据。多个 I/O 请求可以同时挂起。
但是,FSO 也有一些不足之处。如上所述,它只能对文本文件进行操作。要操纵二进制文件,您必须使用指针指向内存地址或字节数组,但 FSO 对象不支持此操作。
此外,当您读取或写入大量内容时,存储在缓冲区中的信息可能会产生很高的内存命中率。还有,您不能管理许可权限或文件和文件夹属性。
实现方法
可以使用 Object Browser(对象浏览器)来查看 FSO 模型的对象、集合、属性、方法、事件和常数。要在 Object Browser(对象浏览器)中查看 FSO,必须首先向 Microsoft 脚本运行时类型库添加一个引用。
向 Microsoft 脚本运行时类型库添加引用
在 Project(项目)菜单上,单击 Add Reference(添加引用)。
在 COM 选项卡上,选择 Microsoft Scripting Runtime(Microsoft 脚本运行时),单击 Select(选择),然后单击 OK(确定)。
现在,FSO 将显示在 Object Browser(对象浏览器)中的 Interop.Scripting 节点内。
使用 FileSystemObject 进行编程:
使用 CreateObject 方法创建一个 FileSystemObject 对象。
将一个变量定义为 FileSystemObject 对象。例如:
Dim MyFileStream as Scripting.New FileSystemObject。
对新创建的对象使用相应的方法。
访问对象的属性。
代码示例
以下示例使用 FileSystemObject 对象的实例来读取文件并写入文件内容。
Public Class UsesScripting
Public Shared Sub Main()
Dim fileSystem As New Scripting.FileSystemObject()
Dim file As Scripting.TextStream
file = fileSystem.OpenTextFile("c:\test.txt", _
Scripting.IOMode.ForReading, False,_
Scripting.Tristate.TristateUseDefault)
Dim contents As String = file.ReadAll()
Console.WriteLine(contents)
file.Close()
End Sub
End Class
.net 框架类
System.IO 命名空间包含 File 和 Directory 类,它们可以提供操纵文件和目录所需的基本功能。由于所有方法都是静态的或是这些对象的共享成员,因此您可以直接使用它们,而无需先创建类的实例。
下表列出了 File 类方法。
方法
说明
AppendText
创建 StreamWriter 的一个实例,将 UTF-8 编码文本附加到现有文件。
Copy
将现有文件复制到新文件。
Create
以指定的完全限定路径创建文件。
CreateText
创建或打开一个新文件,用于编写 UTF-8 编码文本。
Delete
删除指定文件。
Exists
返回 Boolean 值,表明指定文件是否存在。
GetAttributes
返回完全限定路径的文件的 FileAttributes。
GetCreationTime
返回 Date,表示指定文件的创建时间。
GetLastAccessTime
返回 Date,表示最近一次访问指定文件的时间。
GetLastWriteTime
返回 Date,表示最近一次写入指定文件的时间。
Move
将指定文件移到新位置,提供选项以指定新的文件名。
Open
打开指定路径的 FileStream。
OpenRead
打开现有文件以进行读取。
OpenText
打开现有的 UTF-8 编码文本文件以进行读取。
OpenWrite
打开现有文件以进行写入。
SetAttributes
设置指定路径中的文件的指定 FileAttributes。
SetCreationTime
设置指定文件的创建日期和时间。
SetlastAccessTime
设置最近一次访问指定文件的日期和时间。
SetLastWriteTime
设置最近一次写入指定文件的日期和时间。
下表列出了附加到 Directory 类的方法。
方法
说明
CreateDirectory
按 path 的规定创建所有目录和子目录。
Delete
删除指定目录。
Exists
返回 Boolean 值,表明指定目录是否存在。
GetCreationTime
返回 Date,表示指定目录的创建时间。
GetCurrentDirectory
返回 String,表示应用程序的当前工作目录。
GetDirectories
返回 String,表示指定目录中的子目录名称。
GetDirectoryRoot
返回 String,表示指定路径的卷信息、根信息或同时表示这两种信息。
GetFiles
返回 String,表示指定目录中的文件名。
GetFileSystemEntries
返回 String,表示指定目录中所有文件和子目录的名称。
GetLastAccessTime
返回最近一次访问指定目录的日期和时间。
GetLastWriteTime
返回 Date,表示最近一次写入指定目录的时间。
GetLogicalDrives
返回 String,表示计算机的逻辑驱动器的名称。
GetParent
返回 String,表示指定路径的父目录。
Move
将目录及其内容移到新位置。
SetCreationTime
设置指定目录的创建日期和时间。
SetCurrentDirectory
将应用程序的当前工作目录设置为指定目录。
SetLastAccessTime
设置最近一次访问指定目录的日期和时间。
SetLastWriteTime
设置最近一次写入指定目录的日期和时间。
优点和缺点
公共语言运行时能够生成丰富的类库。例如,除基本文件 I/O 外,System.IO 命名空间还提供许多服务,如 FileSystemWatcher 类,允许您监视对文件的更改;以及 FileInfo 和 DirectoryInfo 类,使您可以收集有关指定文件或目录的信息。有关详细信息,请参阅 FileSystemWatcher、FileInfo 和 DirectoryInfo。
同样,公共语言运行时也提供 FileIOPermission 类,允许您控制对文件和目录的访问。这对于使用 Web 窗体的开发人员尤为重要,因为默认情况下,Web 窗体在一个名为 ASPNET 的特定本地用户环境中运行,而 ASPNET 是作为 ASP.NET/框架安装的一部分而创建的。当此类应用程序请求访问资源时,此请求在该用户的环境中进行。不过,在默认情况下,ASPNET 用户只拥有有限的权限,使他们无法执行从 Web 应用程序写入文件等操作。
公共语言运行时也能够与其他 .NET 语言兼容(如 Visual C#?),并有助于保持应用程序之间的一致性,这一点对于企业级的开发尤为重要。
对于刚刚开始熟悉这些新方法的 Visual Basic 程序员而言,不熟悉公共语言运行时可能会遇到一些困难。如果您是其中一员,您可能更倾向于使用您所熟知的方法。
实现方法
如上所述,许多 .net 框架类(如 FileIOPermission)对于使用文件和目录进行工作的 Visual Basic 开发人员都十分有用。Imports 语句允许您在不使用完全限定名称的情况下引用命名空间中的类。
代码示例
以下示例使用 StreamReader 类来读取文本文件的内容。
Imports System
Imports System.IO
Function ReadTextFile(ByVal path As String) As String
Dim sr As System.IO.StreamReader
Dim Contents As String
sr = New StreamReader(path)
Contents = sr.ReadToEnd()
sr.Close()
Return Contents
End Function
以下代码与前面的示例顺序相反,它使用与 StreamWriter 类相同的方法来写入文本文件。
Imports System
Imports System.IO
Sub WriteTextFile(ByVal path As String, ByVal value As String)
Dim sr As StreamWriter
Dim Contents As String
sr = New StreamWriter(path)
sr.Write(value)
sr.Close()
End Sub
以下示例演示了如何使用 FileSystemWatcher 类来监视目录的变化。它声明 FileSystemWatcher 类的一个实例,提供要监视的路径,指示要监视的内容,然后创建一个事件处理程序来监视新文件的创建。
Imports System
Imports System.IO
Imports System.XML
Imports System.XML.Serialization
Class WatchForNewFiles
Shared Sub Main()
Dim fw As New System.IO.FileSystemWatcher()
' 要监视的路径。
fw.Path = "C:\"
' 监视文件。
fw.NotifyFilter = System.IO.NotifyFilters.FileName
fw.IncludeSubdirectories = True
' 添加事件处理程序以监视文件创建。
AddHandler fw.Created, _
New System.IO.FileSystemEventHandler(AddressOf OnFileEvent)
fw.EnableRaisingEvents = True
Console.ReadLine()
End Sub
' 新文件创建时生成的事件。
Shared Sub OnFileEvent(ByVal source As Object, ByVal e As _
System.IO.FileSystemEventArgs)
Console.WriteLine("在 C: 中创建的新文件" & e.FullPath)
End Sub
End Class
以下示例说明了如何使用公共语言运行时类来保存 Visual Basic .NET 类。可以使用 BinaryFormatter 和 BinaryWriter/Binary Reader 类来保存,使用这种方法效率较高,但可读性略差。也可以使用 XMLSerializer 类和 FileStream 类,使用这种方法,移植性较强且易于读取,但效率较低。
Imports System
Imports System.IO
Imports System.Xml
Imports System.Xml.Serialization
Public Module Module1
Public Class class1
Public classvar As Integer
End Class
Sub Main()
Try
Dim Result As Object
' 创建并初始化要保存的类(序列化)。
Dim myclass1 As New class1()
myclass1.classvar = 7
' 创建序列化程序。
Dim xs As New XmlSerializer(GetType(class1))
' 创建文件流。
Dim FStream As New IO.FileStream("c:\xyz.txt", _
IO.FileMode.OpenOrCreate)
' 使用序列化程序编写类。
xs.Serialize(FStream, myclass1)
' 将文件流的位置重置到开始位置。
Fstream.seek(0, IO.SeekOrigin.Begin)
' 通过还原序列化到对象中来完成在类中的读取操作。
Result = xs.Deserialize(FStream)
FStream.Close()
' 将文件流作为文本打开,以 XML 格式读取/打印类。
console.WriteLine(readxml())
Catch e As Exception
console.WriteLine(e.ToString)
End Try
End Sub
Function ReadXML() As String
Dim MyReader As StreamReader = File.OpenText("c:\xyz.txt")
Dim str As String
Dim al As ArrayList = New ArrayList()
Do
str = MyReader.ReadLine()
If str <> Nothing Then
ReadXML &= str & VBcrlf
End If
Loop Until str = Nothing
Return ReadXML
End Function
End Module
总结
在这些方法中,不管是使用 Visual Basic .NET 运行时方法,采用 FileSystemObject 对象,还是使用 .NET 框架函数,根据不同的情况和应用程序,每种方法都各有利弊。对于需要处理大型文件的应用程序而言,使用公共语言运行时函数要比使用 FSO 方法好。对于要与在早期版本中 Visual Basic 编写的应用程序进行交互的应用程序而言,使用 Visual Basic 运行时方法可以达到更佳性能。在每种情况下,您都需要评估应用程序的需求、运行环境以及您驾驭不同方法的能力。
正如您所看到的,从早期版本至今,Visual Basic 不断展示出新的功能,程序员的视野也不断得到扩大。对于大多数人来说,最好是将这些方法结合起来,从而可以根据应用程序的特定需要来选择不同的方法。您既可以继续使用熟悉的方法,也可以进一步探索新方法。