加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

VB.NET 简单介绍文件的读写----流类

(2017-08-15 14:42:59)
标签:

it

分类: VB.NET编程

我们知道在计算机内部处理的数据信息以及存放在在磁盘上的文件,对于计算机而言就是一堆二进制数(字节)。这些字节(甚至是位,但计算机通常按字节对它们进行分组)。只有在程序解析了这些字节时,它们才具有了对用户更有价值的高级含义。

使用高级程序设计语言处理数据的过程,有时候把数据看作字节能使用更多的方法处理该数据。

Visual Studio使用流的概念,把在计算机内部(或者网络中)传输的数据看作像河里流淌的水流,这些数据就是流动的数据流。

一种类似字节的数据类型是stream----―系列有序字节。文件、流向网络的数据、遍历队列的消息甚至在内存中的数组,所有这些都适用于上述描述。

定义流的抽象概念使得应用程序能统一处理这些不同类型的对象。如果一个加密或序列化例程操作一个普通字节流,那么程序无需知道该流是否表示文件、内存块或流向网络的数据。

Visual Studio 提供操作不同类型流的几个类,还提供处理更抽象级数据类的较高级别类。例如,它提供处理表示文件和目录的流。

本文介绍一些用于操作流的类。只要想通过介绍一些较低级别的类(很少使用)和一些较高级别的类(比较容易读写字符串和文件),使得读者快速了解并掌握读写字符串和文件。

下面简要描述了最有用的流类。

1FileStream 类:读写文件中的字节。

2MemoryStream类:读写内存中的字节。

3BinaryReaderBinaryWriter类:读写流中的特定数据类型。

4StringReaderStringWriter类:读写字符串中带有或没带新行的文本。

5StreamReaderStreamWriter类:读写流中带有或没带新行的文本(通常是文件流)。

 

1Stream

Stream类定义了派生流类必须具有的属性和方法。程序便用这些属性和方法能够执行相对普通的流任务,例如,确定该流是否允许写入。

Stream类最有用的属性

1CanRead属性:如果流支持读取,则返回True

2CanSeek属性:如果流支持查找流中的特定位置,则返回True

3CanTimeout属性:如果流支持读写操竹超时,则返回True

4CanWrite属性:如果流支持写入,则返回True

5Length属性:返回流中的字节数。

6Position属性:返回流在其字节中的当前位树。因为流支持查找,所以程序可以设置该值来移到特定位置。

7ReadTimeout属性:确定读操作在超时前等待的毫秒数。

8Writetimeout属性:确定写操作在超时前等待的毫秒数。

 

Stream类最有用的方法

1BeginRead方法:开始异步读取。

2Beginwrite方法:开始异步写入。

3Close方法:关闭流,并释放流使用的任何资源(例如,文件句柄)。

4EndRead方法:等待异步读取完成。

5EndWrite方法:结束异步写入。

6Flush方法:从流的缓冲区中将数据流入基础存储媒体(例如,设备、文件、内存等)。

7Read方法:读取流中的字节,并将当前流的位置向前推进读取的字节数。

8ReadByte方法:读取流中的1个字节,并将当前流的位置向前推进1I字节。

9Seek方法:如果流支持查找,则设置该流的位置。

10SetLength方法:设置流的长度。如果流的当前长度超过新的长度,则删除超长部分。如果流的当前长度短于新的长度,则增加不足部分。流必须支持当前使用的方法的写入和查找功能。

11Write方法:将字节写入流,并将当前位置向前推进写入的字节数。

12WriteByte方法:将1个字节写入流.并将当前位置向前推进1个字节。

 

2FileStream

FileStream类提供文件流表示。由于FileStream类的父类Stream类定义了很多属性和方法。有关这些属性和方法的描述,请参阅本文第1节的内容。

FileStreamStream类的基础上添加了两个有用的新属性。第一个是IsAsync属性(如果己经异步打开FileStream,则该属性返回True)。第二个是Name属性(该属性返回传递给对象的构造函数的文件名)。

该类还添加了两个有用的新方法:Lock方法和Unlock方法。Lock方法锁定文件,以使其他程序能读取却不能修改该文件。Unlock方法则解锁锁定的文件。

使用FileStream的构造函数的多个重载版本能够指定文件名或句柄、文件模式(AppendCreateCreateNewOpenOPenOrCreateTruncate)、访问模式(ReadWriteReadWrite)、文件共享(Inheritable,允许子进程继承文件句柄:NoneReadWriteReadwrute)、缓冲区大小和文件选项(AsynchronousDeleteOnCloseEncryptedNoneRandomAccessSequentialScaneWriteThrough)等参数。

下面的代码显示了一个使用FileStream的小示例。该示例创建一个文件,并使用通用转换格式(Universal Transformation FormatUTF)UTF8Encoding对像将字符串转换成一个字节数组。程序先将字节写入该文件,然后关闭FileStream

完整的代码如下:

Imports System.IO

Imports System.Text

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim file_name As String = Application.StartupPath & "\test.txt"

        Dim file_stream As New FileStream(file_name, FileMode.Create)

        Dim bytes As Byte() = New UTF8Encoding().GetBytes("好 VB.Net 2010 !")

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

        file_stream.Close()

    End Sub

End Class

虽然还有其他编码格式(例如,UTF-7UTF-16),但8-bit UTF编码是Web上最流行、使用最广泛的类型。

如同本例所示,FileStream类只提供读写文件的低级别方法。这些方法能读写字节,而不是我们乐意使用的整数、字符串或其他类型的数据。

BinaryReaderBinaryWriter类比FileStream类更容易读写二进制数据,StringReaderStringWriter能够更容易读写字符串数据。有关更多信息,请参阅后面介绍这些类的相关章节。

下面给出的一个例子,单击按钮1创建一个文件,将文本框1里的文本写入到该文件。单击按钮2把由单击按钮1创建的文件内容读取出来,显示在文本框2里;完整代码如下:

Imports System.IO

Imports System.Text

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim Myw As New FileStream(Application.StartupPath & "\.txt", FileMode.Create)

        Dim MyBytes As Byte() = New UTF8Encoding().GetBytes(TextBox1.Text)

        Dim MyB_Write As BinaryWriter = New BinaryWriter(Myw)

        MyB_Write.Write(MyBytes, 0, MyBytes.Length)

        Myw.Close()

    End Sub

 

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

        Dim Myr As New FileStream(Application.StartupPath & "\.txt", FileMode.Open, FileAccess.Read)

        Myr.Position = 0

        Dim MyB_Read As New BinaryReader(Myr)

        Dim MyFileLength As Integer = CInt(Myr.Length - Myr.Position) - 1

        Dim MyFileData(MyFileLength) As Char

        MyB_Read.Read(MyFileData, 0, MyFileLength)

        Myr.Close()

        TextBox2.Text = ""

        Dim i As Integer

        For i = LBound(MyFileData) To UBound(MyFileData)

            TextBox2.Text = TextBox2.Text & MyFileData(i)

        Next

    End Sub

End Class

 

3MemoryStream

如同FileStreamMemoryStream类也是从Stream类继承而来的。该类表示数据存储在内存中的流。类似FileStream,该类只提供相对简单的读写数据的方法。通常,我们会将较高级别的对象与MemoryStream关联来使该对象的使用变得更加容易。

下面的代码创建了一个MemoryStream对象。然后,程序又创建了与MemoryStream关联的BinaryWrite,并使用它将一些文本写入该流。接着,程序创建了与同一MemoryStream关联的BinaryReader对象。称序使用该流的Seek方法重回该流的开头,然后使用BinaryReader对象的ReadString方法读取MemoryStream外的字符串。

Imports System.IO

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim memory_Stream As New MemoryStream()

        Dim binary_Writer As New BinaryWriter(memory_Stream)

        binary_Writer.Write("我们计划十月一日去杭州旅游。")

 

        Dim binary_reader As New BinaryReader(memory_Stream)

        memory_Stream.Seek(0, SeekOrigin.Begin)

        MessageBox.Show(binary_reader.ReadString())

        binary_reader.Close()

    End Sub

End Class

下列示例所要做的事情与上述示例相同,但使用了StreamWriterStreamReader类代替BinaryWriterBinaryReader。注意,程序在可以使用StreamReader读取内存之前,必须调用StreamWriterFlush方法确保将所有文本写入MemoryStream

Imports System.IO

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim memory_stream As New MemoryStream()

        Dim stream_writer As New StreamWriter(memory_stream)

        stream_writer.Write("我们计划十月一日去杭州旅游。")

        stream_writer.Flush()

 

        Dim stream_reader As New StreamReader(memory_stream)

        memory_stream.Seek(0, SeekOrigin.Begin)

        MessageBox.Show(stream_reader.ReadToEnd())

        stream_reader.Close()

    End Sub

End Class

 

4BinaryReaderBinaryWriter

BinaryReaderBinaryWriter类并不是流类,而是处理流类的辅助类。它们能便用特定编码读写文件中的数据。例如,BinaryReader对象的ReadInt32方法读取流中的一个4字节(32位)的带符号整数。同样,ReadUIntl6方法读取一个2字节(16位)的无符号整数。

这些类仍处于一个比较低的级别,通常,应该使用较高级别的类来读写数据。例如,除非确实需要,否则应不受整数的特殊表示限制。

BinaryReaderBinaryWriter对象都与允许访问底层字节的流对象关联。这两个类都有BaseStream属性(返回底层流的引用)。还要注愈这两个类所提供的Close方法都自动关闭底层流。

BinaryReader类最有用的方法。

1Close方法:关闭BinaryReader及其底层流。

2PeekChar方法:读取流的下一个字符,但不将阅读器的位置向前推进,以便稍后其他方法仍能读取该字符。

3Read方法:读取流中的字符,井将阅读器的位置向前推进。

4ReadBoolean方法:读取流中布尔值(Booleam),并将阅读器的位置向前推进1个字节。

5ReadByte方法:读取流中的l字节,并将阅读器的位置向前推进1个字节。

6ReadBytes方法:从流中读取多个字节,然后将这些字节读入字节数组,并将阅读器的位置向前推进读入的字节数。

7ReadChar方法:读取流中的l字符,并根据该流的编码和该字符将阅读器的位置向前推进。

8ReadChars方法:读取流中的多个字符,将结果返回到字符数组中,并根据该流的编码和这些字符将阅读器的位置向前推进。

9ReadDecimal方法:从流中读取一个十进制值,并将阅读器的位置向前推进16个字节。

10ReadDouble方法:从流中读取一个8字节浮点值,并将阅读器的位置向前推进8个字节。

11ReadIntl6方法:读取流中的一个2字节带符号整数,并将阅读器的位置向前推进2个字节。

12ReadInt32方法:读取流中的一个4字节带符号整数,并将阅读器的位置向前推进4个字节。

13ReadInt64方法:读取流中的一个8字节带符号整数,并将阅读器的位置向前推进8个字节。

14ReadSByte方法:从流中读取一个带符号字节,并将阅读器的位置向前推进1字节。

15ReadSingle方法:读取流中的一个4字节浮点值,并将阅读器的位置向前推进4个字节。

16ReadString方法:从当前流中读取一个字符串,并将阅读器的位置越过该字符串向前推进。该字符串以其长度为前缀。

17ReadUIntl6方法:读取流中的一个2字节无符号整数,并将阅读器的位置向前推进2个字节。

18ReadUInt32方法:读取流中的一个4字节无符号整数,并将阅读器的位置向前推进4个字节。

19ReadUInt64方法:读取流中的一个8字节无符号整数,并将阅读器的位置向前推进8个字节。

 

BinaryReader类提供的方法

1Close方法:关闭BinaryReader及其底层流。

2PeekChar方法:读取流的下一个字符,但不将阅读器的位置向前推进,以便稍后其他方法仍能读取该字符。

3Read方法:读取流中的字符,井将阅读器的位置向前推进。

4ReadBoolean方法:读取流中布尔值(Booleam),并将阅读器的位置向前推进1个字节。

5ReadByte方法:读取流中的l字节,并将阅读器的位置向前推进1个字节。

6ReadBytes方法:从流中读取多个字节,然后将这些字节读入字节数组,并将阅读器的位置向前推进读入的字节数。

7ReadChar方法:读取流中的l字符,并根据该流的编码和该字符将阅读器的位置向前推进。

8ReadChars方法:读取流中的多个字符,将结果返回到字符数组中,并根据该流的编码和这些字符将阅读器的位置向前推进。

9ReadDecimal方法:从流中读取一个十进制值,并将阅读器的位置向前推进16个字节。

10ReadDouble方法:从流中读取一个8字节浮点值,并将阅读器的位置向前推进8个字节。

11ReadIntl6方法:读取流中的一个2字节带符号整数,并将阅读器的位置向前推进2个字节。

12ReadInt32方法:读取流中的一个4字节带符号整数,并将阅读器的位置向前推进4个字节。

13ReadInt64方法:读取流中的一个8字节带符号整数,并将阅读器的位置向前推进8个字节。

14ReadSByte方法:从流中读取一个带符号字节,并将阅读器的位置向前推进1字节

15ReadSingle方法:读取流中的一个4字节浮点值,并将阅读器的位置向前推进4个字节。

16ReadString方法:从当前流中读取一个字符串,并将阅读器的位置越过该字符串向前推进。该字符串以其长度为前缀。

17ReadUIntl6方法:读取流中的一个2字节无符号整数,并将阅读器的位置向前推进2个字节。

18ReadUInt32方法:读取流中的一个4字节无符号整数,并将阅读器的位置向前推进4个字节。

19ReadUInt64方法:读取流中的一个8字节无符号整数,并将阅读器的位置向前推进8个字节。

 

BinaryWriter类最有用的方法。

1Close方法:关闭BinaryWriter及其底层流。

2Flush方法:将任一缓冲数据写入底层流。

3Seek方法:在流内设置位置。

4Write 方法:将位写入流。该方法有很多写入字符、字符数组、整数、字符串、无符号64位整数等的重载版本。

有关BinaryReaderBinaryWriter的使用例子请参见第3节的例子。

 

5StringReaderStringWriter

StringReaderStringWriter类可用来读写字符串中的文本。

这些类从抽象类TextReaderTextWriter派生而来,所以继承了TextReaderTextWriter类中的大部分属性和方法的定义。

StringReader类最有用的方法。

1Close方法:关闭阅读器,并释放阅读器正使用的任何资源。

2Peek方法:在不改变阅读器的状态下,从文本中读取下一个字符,以便稍后其他方法可以读取该字符。

3Read方法:从输入中读取数据。该方法的重载版本读取单个字符或定长的字符数组。

4ReadBlock方法:将输入中的数据读入字符数组。

5ReadLine方法:从输入中读取一行字符,并将该数据作为一个字符串返回。

6ReadToEnd方法:读取输入中的其余字符,并将它们作为一个字符串返回。

StringWriter类具有三个有用的属性:EncodingFormatProviderNewLineEncoding属性指定文本的编码(ASCllUTF-8Unicode等)。

FormatProvider属性返回控制格式的对象。例如,可以构建一个FormatProvider对象,该对象知道如何在不同的进制中显示数字(例如,十六进制或八进制)。

NewLine属性获取或设置书写器使用的字符串来结束行。通常,该值类似于回车或回车加换行。

 

StringWriter类最有用的方法。

1Close方法:关闭书写器,并释放其实用的任何资源。

2Flush方法:将任一缓冲数据写入底层输出。

3Write方法:将值写入愉出。该方法具有很多写入字符、字符数组、整数、字符串、无符号64位整数等重载版本。

4WriteLine方法:按照新行序列将数据写入愉出。

StringReader提供从字符串中读取行、字符或字符块的方法。它的ReadToEnd方法返回己经不读取的任一字符串。StringReader的构造函数以其应处理的字符串作为参数。

StringWriter类能用来构建字符串。该类提供将文本写入字符串(带有或没带新行字符)的方法。该类的Tostring方法则返回StringWriter的字符串。

StringWriter在底层StringBuilder类中存储它的字符串。StringBuilder能更有效率地构建字符串。例如,如果通过连接一系列长子串,应用程序构建一个非常庞大的字符串,则实用StringBuilder比将字符串添加到正常String变量更有效率,StringWriter提供了StringBuilder类的简单接口。

StringWriter提供的最有用方法不是由TextWrinter的父类GetStringBuilder定义的。该方法返回存放该类的数据的底层StringBuilder对象的引用。

下面的代码显示了一个使用StringWriterStringReader类的简单示例。该示例创建StringWriter对象,并使用WriteLine方法将两行添加到字符串。然后,显示书写器的Tostring方法的结果。该方法返回书写器的当前内容。接着,创建StringReader,将要读取的字符串传递给它的构造函数。因为程序不再需要添加内容,所以关闭StringWriter。程序显示StringReaderReadLine方法的结果。因为StringWriter创建了字符串,并把该字符串作为两个独立行,所以该程序只显示第一行----The quick brown fox”。接着,程序使用StringReaderReadToFnd方法来读取和显示文本的剩余部分----jumps over the lazy dog”。最后,通过关闭StringReader完成该代码。

Imports System.IO

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        'Use a StringWriter to write into a string.

        Dim String_writer As New StringWriter()

        String_writer.WriteLine("The quick brown fox")

        String_writer.WriteLine("jumps over the lazy dog.")

        MessageBox.Show(String_writer.ToString)

 

        'Use a StringReader to read from the string.

        Dim String_reader As New StringReader(String_writer.ToString)

        String_writer.Close()

        MessageBox.Show(String_reader.ReadLine())

        MessageBox.Show(String_reader.ReadToEnd())

        String_reader.Close()

    End Sub

End Class

 

6StreamReaderStreamWriter

StreamReaderStreamWriter类能用来读写流中的数据。

这两个类也是从TextReaderTextWriter类派生而来,并分别继承了它们的大部分属性和方法。所以有关StreamReaderStreamWriter的方法请参阅第5StringReaderStringWriter类的方法,所以这里不再列举。

通常,底层流为FileStream。可以将FileStream传入这些类的构造函数中,或将自动创建FileStream的文件名和对象传入其中。

StreamReader类提供从流中读取行、字符或字符块的方法。该类的ReadToEnd方法返回已经不读取的任一流。

StreamWriter类提供将文本写入带有或没带换行字符的流中的方法

StreamReaderStreamWriter是由TextReaderTextWriter类派生而来,并继承这些类的大部分属性和方法的定义。有关这些属性和方法的描述,请参阅本章前面介绍的第6节。

StreamWriter类添加一个新的AutoFlush属性,该属性确定是否书写器在每次写入后都会刷新其缓冲区。

下面的简单示例显示了如何使用StreamReaderStreamWriter。程序生成一个文件名,并将该文件名传入StreamWriter的构造函数中。程序先使用StreamWriterWriteWriteLine方法将两行文本放入该文件:然后,关闭该文件。如果马上使用文本编辑器打开该文件,则会看到该文本。然后,程序创建一个新的StreamReader,将同一文件名传递给它的构造函数。程序使用阅读器的ReadToEnd方法来挖掘该文件的内容,并显示结果。

Imports System.IO

Public Class Form1

    Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

        Dim file_name As String = Application.StartupPath & "\test.txt"

        Dim Stream_writer As New StreamWriter(file_name)

        Stream_writer.Write("The quick brown fox")

        Stream_writer.WriteLine(" jumps over the lazy dog.")

        Stream_writer.Close()

 

        Dim stream_reader As New StreamReader(file_name)

        MessageBox.Show(stream_reader.ReadToEnd())

        stream_reader.Close()

    End Sub

End Class

该示例使用了FileStream对象的较低级别的WriteRcad方法操作字节数组,这使其看起来相当冗长、烦琐。请将该程序与本章前面介绍的第2节中的示例进行比较。

下面一个例子,演示了如何把文本框里的文本写入到指定的文件里,然后读取指定文件的内容并显示在文本框里。

Imports System.IO

Public Class Form1

    Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles MyBase.Load

        TextBox1.Text = "今天天气正好。" & vbCrLf & "我们打算下午去图书馆查资料。"

    End Sub

 

Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click

   把文本框里的文本写入到指定的文件里

        Dim file_name As String = Application.StartupPath & "\test.txt"

        Dim Stream_writer As New StreamWriter(file_name)

        Stream_writer.Write(TextBox1.Text)

        Stream_writer.Close()

    End Sub

 

    Private Sub Button2_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button2.Click

       读取指定文件的内容并显示在文本框里

Dim file_name As String = Application.StartupPath & "\test.txt"

        Dim stream_reader As New StreamReader(file_name)

        TextBox2.Text = stream_reader.ReadToEnd()

        stream_reader.Close()

    End Sub

End Class

 

7节 小结

流能让程序在同等条件下考虑各种数据源。如果子例程将流作为参数,则它不会注意该流是否与字符串、文件、内存块或网络连接关联。

很多应用程序使用StringReaderStringWriter类来读写字符串中的文本,而使用StreamReaderStreamWriter类读写流中的文木(通常是文件)。其他流类常用于较低级别或用作更抽象的类来允许例程在同等条件下处理不同类型的流,如果重点关注这4个类,则将很快学会如何执行最常见的流操作。

程序常使用StreamReaderStreamWriter类来读写文件。

 

文中的示例代码,都在VB.NET 2010中通过运行测试。

有不当之处敬请指正。

2017年8月15日

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有