ZetCode

Visual Basic 输入和输出

最后修改于 2023 年 10 月 18 日

本章专门介绍 Visual Basic 中的输入和输出。Visual Basic 中的输入和输出基于流。

流是用于处理输入和输出的对象。流是字节序列的抽象,例如文件、输入/输出设备、进程间通信管道或 TCP/IP 套接字。在 Visual Basic 中,我们有一个 Stream 类,它是所有流的抽象类。还有其他从 Stream 类派生的类,使编程变得更容易。

MemoryStream

MemoryStream 是一个处理计算机内存中数据的流。

Program.vb
Option Strict On

Imports System.IO

Module Example

   Sub Main()

      Dim ms As Stream = New MemoryStream(6)

      ms.WriteByte(9)
      ms.WriteByte(11)
      ms.WriteByte(6)
      ms.WriteByte(8)
      ms.WriteByte(3)
      ms.WriteByte(7)

      ms.Position = 0

      Dim rs As Integer
      rs = ms.ReadByte()

      Do While rs <> -1
        Console.WriteLine(rs)
        rs = ms.ReadByte()
      Loop

      ms.Close()

   End Sub

End Module

我们使用 MemoryStream 将六个数字写入内存。然后我们读取这些数字并将它们打印到控制台。

Dim ms As Stream = New MemoryStream(6)

该行创建并初始化一个容量为六个字节的 MemoryStream 对象。

ms.Position = 0

我们使用 Position 属性将光标在流中的位置设置为开头。

ms.WriteByte(9)
ms.WriteByte(11)
ms.WriteByte(6)
...

WriteByte 方法将一个字节写入当前流的当前位置。

Do While rs <> -1
  Console.WriteLine(rs)
  rs = ms.ReadByte()
Loop

在这里,我们从流中读取所有字节并将它们打印到控制台。

ms.Close()

最后,我们关闭流。

$ dotnet run
9
11
6
8
3
7

StreamReader 和 StreamWriter

StreamReader 从字节流中读取字符。它默认为 UTF-8 编码。StreamWriter 将字符以特定编码写入流。

Program.vb
Option Strict On

Imports System.IO

Module Example

   Sub Main()

       Dim file As String
       file = "languages"

       Try
           Dim stream As StreamReader
           stream = New StreamReader(file)
           Console.WriteLine(stream.ReadToEnd())
       Catch e As IOException
           Console.WriteLine("Cannot read file.")
       End Try

   End Sub

End Module

我们有一个名为 languages 的文件。我们从该文件中读取字符并将它们打印到控制台。

Dim stream As StreamReader
stream = New StreamReader(file)

StreamReader 接受文件名作为参数。

Console.WriteLine(stream.ReadToEnd())

ReadToEnd 方法读取所有字符直到流的末尾。

$ cat languages
Python
Visual Basic
PERL
Java
C
C#
$ dotnet run
Python
Visual Basic
PERL
Java
C
C#

我们在当前目录中有一个 languages 文件。我们将文件的所有行打印到控制台。

在下一个示例中,我们计算行数。

Program.vb
Option Strict On

Imports System.IO

Module Example

   Sub Main()

       Dim file As String
       Dim count As Integer

       file = "languages"

       Try
           Dim stream As StreamReader
           stream = New StreamReader(file)

           While Not (stream.ReadLine() Is Nothing)
               count += 1
           End While

       Catch e As IOException
           Console.WriteLine("Cannot read file.")
       End Try

       Console.WriteLine("There are {0} lines", count)

   End Sub

End Module

计算文件中的行数。

While Not (stream.ReadLine() Is Nothing)
    count += 1
End While

在 While 循环中,我们使用 ReadLine 方法从流中读取一行。它从流中返回一行,如果到达输入流的末尾,则返回 Nothing。

下面是使用 StreamWriter 的示例。

Program.vb
Option Strict On

Imports System.IO

Module Example

   Sub Main()

      Dim mstream As New MemoryStream()
      Dim swriter As New StreamWriter(mstream)

      swriter.Write("ZetCode, tutorials for programmers.")
      swriter.Flush()

      Dim sreader As New StreamReader(mstream)
      Console.WriteLine(sreader.ReadToEnd())
      sreader.Close()

   End Sub

End Module

在前面的示例中,我们将字符写入内存。

Dim mstream As New MemoryStream()

创建了 MemoryStream

Dim swriter As New StreamWriter(mstream)

StreamWriter 类将内存流作为参数。通过这种方式,我们将写入内存流。

swriter.Write("ZetCode, tutorials for programmers.")
swriter.Flush()

我们将一些文本写入写入器。Flush 清除当前写入器的所有缓冲区,并导致任何缓冲的数据被写入基础流。

Dim sreader As New StreamReader(mstream)
Console.WriteLine(sreader.ReadToEnd())

现在我们创建一个流读取器的实例并读回我们写的所有内容。

FileStream

FileStream 类使用文件系统上文件的流。此类可用于从文件读取、写入文件、打开和关闭文件。

Program.vb
Option Strict On

Imports System.IO
Imports System.Text

Module Example

   Sub Main()
        Dim fstream As New FileStream("author", FileMode.Append)
        Dim bytes As Byte() = New UTF8Encoding().GetBytes("Фёдор Михайлович Достоевский")

        fstream.Write(bytes, 0, bytes.Length)
        fstream.Close()
   End Sub

End Module

我们将一些俄语西里尔字母的文本写入当前工作目录中的文件中。

Dim fstream As New FileStream("author", FileMode.Append)

创建了 FileStream 对象。第二个参数是模式,文件将以该模式打开。append 模式打开文件(如果存在)并定位到文件的末尾,或者创建一个新文件。

Dim bytes As Byte() = New UTF8Encoding().GetBytes("Фёдор Михайлович Достоевский")

我们从俄语 azbuka 中的文本创建一个字节数组。

fstream.Write(bytes, 0, bytes.Length)

我们将字节写入文件流。

XmlTextReader

我们可以使用流来读取 XML 数据。XmlTextReader 是在 Visual Basic 中读取 XML 文件的类。该类是前向只读的。

我们有以下 XML 测试文件。

<?xml version="1.0" encoding="utf-8" ?>
<languages>
    <language>Python</language>
    <language>Ruby</language>
    <language>Javascript</language>
    <language>C#</language>
</languages>
Program.vb
Option Strict On

Imports System.IO
Imports System.Xml

Module Example

    Sub Main()

        Dim file As String
        file = "languages.xml"

        Try
            Dim xreader As New XmlTextReader(file)

            xreader.MoveToContent()

            Do While xreader.Read()
                Select Case xreader.NodeType
                    Case XmlNodeType.Element
                        Console.Write(xreader.Name & ": ")
                    Case XmlNodeType.Text
                        Console.WriteLine(xreader.Value)
                End Select
            Loop

            xreader.Close()

        Catch e As IOException
            Console.WriteLine("Cannot read file.")
        Catch e As XmlException
            Console.WriteLine("XML parse error")
        End Try

     End Sub

End Module

这个 Visual Basic 程序从先前指定的 XML 文件中读取数据并将其打印到终端。

Dim xreader As New XmlTextReader(file)

创建了 XmlTextReader 对象。它将文件名作为参数。

xreader.MoveToContent()

MoveToContent 方法移动到 XML 文件的实际内容。

Do While xreader.Read()

此行从流中读取下一个节点。

Case XmlNodeType.Element
    Console.Write(xreader.Name & ": ")
Case XmlNodeType.Text
    Console.WriteLine(xreader.Value)

在这里,我们打印元素名称和元素文本。

Catch e As XmlException
    Console.WriteLine("XML parse error")

我们检查 XML 解析错误。

$ dotnet run
language: Python
language: Ruby
language: Javascript
language: C#

文件和目录

.NET framework 提供了其他类,我们可以使用它们来处理文件和目录。

File 类是一个更高级别的类,它具有用于文件创建、删除、复制、移动和打开的共享方法。这些方法使工作更容易。

Program.vb
Option Strict On

Imports System.IO

Module Example

    Sub Main()
       Try
            Dim sw As StreamWriter

            sw = File.CreateText("cars")

            sw.WriteLine("Toyota")
            sw.WriteLine("Skoda")
            sw.WriteLine("BMW")
            sw.WriteLine("Volkswagen")
            sw.WriteLine("Volvo")

            sw.Close()
       Catch e As IOException
           Console.WriteLine("IO error")
       End Try

    End Sub

End Module

在这个例子中,我们创建一个 cars 文件并将一些汽车名称写入其中。

sw = File.CreateText("cars")

CreateText 方法创建或打开一个文件用于写入 UTF-8 编码的文本。它返回一个 StreamWriter 对象。

sw.WriteLine("Toyota")
sw.WriteLine("Skoda")
...

我们将两行写入流。

Program.vb
Option Strict On

Imports System.IO

Module Example

    Sub Main()

        If File.Exists("cars")
            Console.WriteLine(File.GetCreationTime("cars"))
            Console.WriteLine(File.GetLastWriteTime("cars"))
            Console.WriteLine(File.GetLastAccessTime("cars"))
        End If

        File.Copy("cars", "newcars")

    End Sub

End Module

在第二个示例中,我们展示了 File 类的其他五个共享方法。

If File.Exists("cars")

Exists 方法确定指定的文件是否存在。

Console.WriteLine(File.GetCreationTime("cars"))
Console.WriteLine(File.GetLastWriteTime("cars"))
Console.WriteLine(File.GetLastAccessTime("cars"))

我们获取指定文件的创建时间、上次写入时间和上次访问时间。

File.Copy("cars", "newcars")

Copy 方法复制文件。

My.Computer.FileSystem 是一个对象,它提供了用于处理驱动器、文件和目录的属性和方法。

Program.vb
Option Strict On

Imports System.IO

Module Example

    Sub Main()

        Try
            My.Computer.FileSystem.CreateDirectory("temp")
            My.Computer.FileSystem.CreateDirectory("newdir")
            My.Computer.FileSystem.MoveDirectory("temp", "temporary")
        Catch e As IOException
            Console.WriteLine("Cannot create directories")
            Console.WriteLine(e.Message)
        End Try

    End Sub

End Module

我们使用上述对象中的两种方法。

My.Computer.FileSystem.CreateDirectory("temp")

CreateDirectory 方法创建一个新目录。

My.Computer.FileSystem.MoveDirectory("temp", "temporary")

MoveDirectory 方法为指定目录提供一个新名称。

DirectoryInfoDirectory 具有用于创建、移动和枚举目录和子目录的方法。

Program.vb
Option Strict On

Imports System.IO

Module Example

    Dim subDir As IO.DirectoryInfo
    Dim dir As New IO.DirectoryInfo("../io")

    Dim fileName As String

    Dim files As String() = Directory.GetFiles("../io")
    Dim dirs As DirectoryInfo() = dir.GetDirectories()

    Sub Main()

        For Each subDir In dirs
            Console.WriteLine(subDir.Name)
        Next

        For Each fileName In files
            Console.WriteLine(fileName)
        Next

    End Sub

End Module

我们使用 DirectoryInfo 类来遍历特定目录并打印其内容。

Dim dir As New IO.DirectoryInfo("../io")

我们展示了这个目录 (io) 的内容。

Dim files As String() = Directory.GetFiles("../io")

我们使用共享的 GetFiles 方法获取 io 目录的所有文件。

Dim dirs As DirectoryInfo() = dir.GetDirectories()

我们获取所有目录。

For Each subDir In dirs
    Console.WriteLine(subDir.Name)
Next

在这里,我们循环遍历目录并将它们的名称打印到控制台。

For Each fileName In files
    Console.WriteLine(fileName)
Next

在这里,我们循环遍历文件数组并将它们的名称打印到控制台。

$ dotnet run
newdir
temp
temporary
../io/append.vb
../io/append.vb~
../io/author
../io/cars
...

在本章中,我们介绍了 Visual Basic 中的输入和输出操作。