# 输入和输出

> 原文： [https://zetcode.com/lang/visualbasic/io/](https://zetcode.com/lang/visualbasic/io/)

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

流是与输入和输出一起使用的对象。 流是字节序列的抽象，例如文件，输入/输出设备，进程间通信管道或 TCP/IP 套接字。 在 Visual Basic 中，我们有一个`Stream`类，它是所有流的抽象类。 还有一些其他类可以从`Stream`类派生而来，从而使编程更加容易。

## `MemoryStream`

`MemoryStream`是用于处理计算机内存中数据的流。

```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`将六个数字写入存储器。 然后，我们读取这些数字并将其打印到控制台。

```vb
Dim ms As Stream = New MemoryStream(6)

```

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

```vb
ms.Position = 0

```

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

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

```

`WriteByte()`方法在当前位置的当前流中写入一个字节。

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

```

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

```vb
ms.Close()

```

最后，我们关闭流。

```vb
$ ./memory.exe 
9
11
6
8
3
7

```

示例的输出。

## `StreamReader` & `StreamWriter`

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

```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`的文件。 我们从该文件中读取字符并将其打印到控制台。

```vb
Dim stream As StreamReader
stream = New StreamReader(file)

```

`StreamReader`以文件名作为参数。

```vb
Console.WriteLine(stream.ReadToEnd())

```

`ReadToEnd()`方法读取所有字符到流的末尾。

```vb
$ cat languages 
Python
Visual Basic
PERL
Java
C
C#
$ ./readfile.exe 
Python
Visual Basic
PERL
Java
C
C#

```

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

在下一个示例中，我们将对行进行计数。

```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

```

计算文件中的行数。

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

```

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

以下是`StreamWriter`的示例。

```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

```

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

```vb
Dim mstream As New MemoryStream()

```

创建了`MemoryStream`。

```vb
Dim swriter As New StreamWriter(mstream)

```

`StreamWriter`类将内存流作为参数。 这样，我们将要写入内存流。

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

```

我们写一些文字给作家。 `Flush()`清除当前写入器的所有缓冲区，并使所有缓冲的数据写入基础流。

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

```

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

## `FileStream`

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

```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

```

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

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

```

创建一个`FileStream`对象。 第二个参数是打开文件的模式。 附加模式将打开文件（如果存在）并查找到文件末尾，或创建一个新文件。

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

```

我们使用俄语西里尔字母中的文本创建字节数组。

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

```

我们将字节写入文件流。

## `XmlTextReader`

我们可以使用流来读取 XML 数据。 `XmlTextReader`是在 Visual Basic 中读取 XML 文件的类。 该类是仅转发和只读的。

我们有以下 XML 测试文件。

```vb
<?xml version="1.0" encoding="utf-8" ?>
<languages>
    <language>Python</language>
    <language>Ruby</language>   
    <language>Javascript</language>
    <language>C#</language>
</languages>

```

```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 文件中读取数据并将其打印到终端。

```vb
Dim xreader As New XmlTextReader(file)

```

创建一个`XmlTextReader`对象。 它以文件名作为参数。

```vb
xreader.MoveToContent()

```

`MoveToContent()`方法移至 XML 文件的实际内容。

```vb
Do While xreader.Read()

```

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

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

```

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

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

```

我们检查 XML 解析错误。

```vb
$ ./readxml.exe 
language: Python
language: Ruby
language: Javascript
language: C#

```

示例输出。

## 文件和目录

.NET 框架提供了其他类，我们可以使用这些类来处理文件和目录。

`File`类是更高级别的类，具有用于文件创建，删除，复制，移动和打开的共享方法。 这些方法使工作更加轻松。

```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`文件，并在其中写入了一些汽车名称。

```vb
sw = File.CreateText("cars")

```

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

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

```

我们向流写入两行。

```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`类的其他五个共享方法。

```vb
If File.Exists("cars")

```

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

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

```

我们得到指定文件的创建时间，上次写入时间和上次访问时间。

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

```

`Copy()`方法复制文件。

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

```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

```

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

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

```

`CreateDirectory()`方法创建一个新目录。

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

```

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

`DirectoryInfo`和`Directory`具有用于创建，移动和枚举目录和子目录的方法。

```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`类遍历特定目录并打印其内容。

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

```

我们将显示该目录（`io`）的内容。

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

```

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

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

```

我们得到所有目录。

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

```

在这里，我们遍历目录并将其名称打印到控制台。

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

```

在这里，我们遍历文件数组并将其名称打印到控制台。

```vb
$ ./showcontents.exe 
newdir
temp
temporary
../io/append.exe
../io/append.vb
../io/append.vb~
../io/author
../io/cars
...

```

示例的输出。

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