004集——Put 语句将一个变量的数据写入磁盘文件中(VBA)

PUT语句语法如下:

语法

Put [#]filenumber, [recnumber], varname

Put 语句的语法具有以下几个部分:

部分 描述
filenumber 必要。任何有效的文件号
recnumber 可选。Variant (Long)。记录号(Random 方式的文件)或字节数(Binary 方式的文件),指明在此处开始写入。
varname 必要。包含要写入磁盘的数据的变量名。

关于什么是random方式,我们有必要详细说明下。在本博之前的文章中有详细介绍open函数,我们知道mode有以下几种:

mode 必要。关键字,指定文件方式,有 AppendBinaryInputOutput、或 Random 方式。如果未指定方式,则以 Random 访问方式打开文件。

        Append为追加输入内容,Binary为二进制文件方式,Random为随机方式,但是什么时候用random模式呢?

        答案为打开随机文件时用随机模式。

        紧接着问题来了,什么是随机文件?首先我们了解下文件的读写。(是不是感觉问题越来越多?研究一个问题,一下子碰到十个问题需要搞懂)

        按照文件的读写方式的不同,我们可以把计算机的文件分成顺序文件,随机文件和二进制文件。

1 顺序文件

        是指按储存相同的顺序找回数据的文件。例如以CSV格式(逗号分割文本),TXT 格式(以Tab键分割的文本)或者PRN格式(以空格分隔的文本)储存的文件。顺序文件访问经常用来写文本文件,例如错误日志,参数设定和报告。

顺序文件有下列模式:Input(读), Output(写) 和 Append(追加写),模式决定了文件打开后你如何使用它。

2 随机文件

        是指随机访问的文本文件,它的数据以同等长度储存并在一个以逗号分割的区域了。随机访问 文件只有一个模式——Random

3 二进制文件

        二进制访问文件是图形文件和其它非文本文件。二进制文件只能够在Binary模式下访问。

顺序文件、随机文件的区别

        我们要清楚,所谓的顺序文件、随机文件,是指文件的读写方式,而不是指文件的类型。那就是:

        顺序文件是按行读取,由于每一行的字符数是不一定相同的,所以只能够从头到尾按顺序一行一行地读取,要想直接从中取出某一行是做不到的。(例如打开一个txt小说,一行和下一行之间有个换行)

        而随机文件则是按“块”读取,就是说把文件分割为一个个字数相等的小块,然后根据需要就可以从中取出任意的一块或多块了。(有些数据文件中间没换行)

        再来个例子:顺序文件就像是把一大堆各种种类的书籍杂乱地堆在一起,如果想从中找到某本书,那么就要一本本地去找,运气好的话,可能只找几本就找到了,当然如果运气差就有可能找到最后一本才找到;

        随机文件则是预先把书籍分门别类放到一个个相同大小的、编了号的架子里,只要告知你你要的书在第几的架子里,你直接去这个架子就找就可以了。

 顺序文件和随机文件的记录编辑

        顺序文件是记录按其在文件中的逻辑顺序依次存储进入存储介质中的,其逻辑顺序和物理顺序一致。

        随机文件,由记录组成,能够随机存取其机同长度的数据记录,每一数据记录内可以设计各种栏位以容纳不同的数据。

所以由上面的文件记录特点来看顺序文件又可以分成顺序有序文件和顺序无序文件

顺序有序文件:记录按其主关键字有序的顺序文件为顺序有序文件。

顺序无序文件:记录未按其主关键字有序排列的顺序文件为顺序有序文件。

为提高检索效率,常将顺序文件组织成有序文件。

        二进制文件的特点 二进制文件即除文本文件以外的文件。相对于文本文件两者有着明显的不同:

文本文件是一种由很多行字符构成的计算机文件。文本文件存在于计算机系统中,通常在文本文件最后一行放置文件结束标志。文本文件的编码基于字符定长,译码相对要容易一些;二进制文件编码是变长的,灵活利用率要高,而译码要难一些,不同的二进制文件译码方式是不同的。

        当某文件包含结构数据时,就以随机模式打开它。以随机模式打开文件你可以做到:同时读写、快速访问某特别记录。

        随机文件有什么特点呢?原来,在随机文件里,所有记录都是等长度的,并且每条记录都有相同数目的固定大小区域。记录或者区域的长度必须在文件写入数据之前就确定。如果写入某区域的字符串长度小于该区域的大小,那么VBA就会自动在该字符串后面加空格来填充区域。如果写入的文本比区域长度长的话,超出的字符就不会被写入。说到这里,你是不是看到了数据库的影子呢?数据库就是这样,有很多朋友问到数据库的相关问题,在这套“VBA代码解决方案”中虽然会有所涉及,但不会很多,在之后,会专门出一本关于数据库的书。

        再次归纳一下,随机文件是储存的记录可以随机访问的文件,这意味着随机文件里的任何记录都可以读取,而不必读取它之前的每条记录。这是同顺序文件的最为显著的区别。

        为什么要自定义一种数据类型呢?因为在操作随机文件时经常会用到这类自定义的数据类型,或者说你在建立数据库时会事先定义数据的类型,当你再次访问这类数据时要定义一个与之匹配的数据类型为好。

        在VBA中,允许你在模块的上面使用Type…End Type语句定义一个非标准的数据类型。这种非标准数据类型也经常成为用户自定义的数据类型。用户自定义数据类型可以包括各种数据类型(字符串,整型,日期等等)的内容。当你在使用随机访问的文件时,该变量使你可以轻易地访问个别记录。

下面我们将实例说明一下如何自定义一个数据类型:

Option Explicit

Type MyDictionary

myen As String * 10

mysp As String * 20

End Type

Sub Mytype()

Dim myrecord As MyDictionary '声明一个MyDictionary类型的变量

myrecord.myen = InputBox("请输入一个数据", "记录信息")

myrecord.mysp = InputBox("请输入另一个数据", "记录信息")

MsgBox "数据1:" & myrecord.myen & vbLf & "数据2:" & myrecord.mysp, vbOKOnly, "基本信息"

MsgBox "数据1的长度:" & Len(myrecord.myen) & vbLf & "数据2的长度:" & Len(myrecord.mysp), vbOKOnly, "基本信息"

End Sub

 上面的例子中,用户定义的名为MyDictionary的类型包括两个声明为String(字符串)的项目,并且有特定的大小。成员myen10个字符,第二个项目mysp20个字符。

        不管你输入的是1个字符还是100个字符,最后数据1的长度是10,数据2的长度是20,和我们的定义是完全一致的。这就是自定义数据的神奇之处。

说明

通常用 GetPut 写入的文件数据读出来。

文件中的第一个记录或字节位于位置 1,第二个记录或字节位于位置 2,依此类推。如果省略 recnumber,则将上一个 GetPut 语句之后的(或上一个 Seek 函数指出的)下一个记录或字节写入。所有用于分界的逗号都必须罗列出来,例如:

Put #4,,FileBuffer

下列规则适用于以 Random 方式打开的文件:

  • 如果已写入的数据的长度小于 Open 语句的 Len 子句指定的长度,则 Put 以记录长度为边界写入随后的记录。记录终点与下一个记录起点之间的空白将用现有文件缓冲区内的内容填充。因为填入的数据量无法确定,所以一般说来,最好设法使记录的长度与写入的数据长度一致。如果写入的数据长度大于由 Open 语句的 Len 子句所指定的长度,就会导致错误发生。


     
  • 如果写入的变量是一个可变长度的字符串,则 Put 先写入一个含有字符串长度的双字节描述符,然后再写入变量。Open 语句的 Len 子句所指定的记录长度至少要比实际字符串的长度多两个字节。


     
  • 如果写入的变量是数值类型Variant Put 先写入两个字节来辨认 Variant VarType,然后才写入变量。例如,当写入 VarType 3 的 Variant 时,Put 会写入六个字节:其中,前两个字节辨认出 Variant VarType 3 (Long),后四个字节则包含 Long 类型的数据。Open 语句的 Len 子句所指定的记录长度必须至少比储存变量所需的实际字节多两个字节。

    注意 Put 语句可用来将一个 Variant 数组写入磁盘,但不能用来将包含数组的标量 Variant 写入磁盘。Put 也不能用来将对象写入磁盘。

  • 如果写入的变量是 VarType 8 (String) 的 Variant,则 Put 先写入两个字节来辨认 VarType,接下来的两个字节则指出字符串的长度,然后再写入字符串数据。Open 语句的 Len 子句所指定的记录长度必须至少比实际的字符串长度多四个字节。


     
  • 如果写入的变量是动态数组,则 Put 写入一个描述符,其长度等于 2 加上 8 乘以维数,即 2 + 8 * NumberOfDimensionsOpen 语句的 Len 子句所指定的记录长度必须大于或等於为读出数组数据和数组描述符所需要的所有字节数总和。例如,在将数组写入磁盘时,下列数组声名需要 118 个字节的空间:
    Dim MyArray(1 To 5,1 To 10) As Integer
    
  • 这 118 个字节的分配情况如下:18 个字节用于描述符 (2 + 8 * 2),100 个字节用于数据 (5 * 10 * 2)。


     
  • 如果写入的变量是大小固定的数组,则 Put 只写入数据。它不将描述符写入磁盘。


     
  • 如果写入的变量是任何其他类型的变量(不是可变长度的字符串或 Variant),则 Put 只写入变量数据。Open 语句的 Len 子句所指定的记录长度必须大于或等於要读出的数据长度。


     
  • Put 写入用户定义类型的元素时,除了不在元素之间进行填充外,好象是单独地写入每一个元素。在磁盘上,有一个描述符位于 Put 写入的用户定义的类型的动态数组之前,其长度等于 2 加上 8 乘以维数,即 2 + 8 * NumberOfDimensionsOpen 语句中的 Len 子句所指定的记录长度必须大于或等於为写入各个元素(包括任何数组及其描述符在内)所需的全部字节数总和。

对于以 Binary 方式打开的文件,上述所有 Random 规则都适用,除了:

  • Open 语句中的 Len 子句不起作用。Put 语句连续地将所有变量写入磁盘;也就是说,两个记录之间没有任何填充。


     
  • 对于任何不属于用户定义的类型的数组,Put 只写入数据。它不会写入描述符。


     
  • 对于非用户定义的类型的可变长度字符串,Put 将其直接写入,而无须有双字节描述符。写入的字节数等于字符串所包含的字符数。例如,下列语句将十个字节写入文件号为 1 的文件中:
    VarString$ = String$(10, )
    Put #1,,VarString$
    

我们以random打开写入一个文件,代码如下,在文件中写入固定长度格式的数据,然后打开这个文件,统计出记录数计总字节数,并把文件内容输出到excel中

Type Record    ' 定义用户自定义数据类型。
    ID As Integer
    Name As String * 20
End Type

Type MyDictionary

myen As Integer   '如果定义为字符串,长度2字节,那么输出的序号为乱码,同理,定义字符串长度为2,也是乱码

mysp As String * 20

End Type

Sub MyoutDictionary()

Dim d As MyDictionary

Dim i As Integer

Dim recNr As Long

Dim records As String
Dim myrecord As Record, RecordNumber    ' 声明变量。
' 以随机访问方式打开文件。
Dim TESTFILE
TESTFILE = "C:\Users\Administrator\Desktop\5.txt"
Open TESTFILE For Random As #1 Len = Len(myrecord) '读取编码方式为myrecord的长度为一组编码进行读取并解译编码,否则会乱码
For RecordNumber = 1 To 100   ' 循环6次。
    myrecord.ID = RecordNumber    ' 定义 ID。
    myrecord.Name = "山南水北" & RecordNumber    ' 建立字符串。
    Put #1, RecordNumber, myrecord    ' 将记录写入文件中。
'     MsgBox Len(myrecord.ID)
'     MsgBox Len(myrecord.Name)
'     MsgBox Len(TESTFILE)
Next RecordNumber

Close #1    ' 关闭文件。

Open "C:\Users\Administrator\Desktop\5.txt" For Random As #1 Len = Len(d) '打开随机访问文件

recNr = LOF(1) / Len(d) '计算总记录数
MsgBox "这个文件有" & LOF(1) & "个字节," & vbCr & "总记录数: " & recNr ' 提示本文件的总字节数

For i = 1 To recNr

Seek #1, i ' 找到该随机记录

Get #1, i, d ' 读取记录

Sheets("sheet1").Cells(i, 1) = d.myen

Sheets("sheet1").Cells(i, 2) = d.mysp

Next

Close #1 ' 关闭文件

End Sub

 此代码中用到seek函数和get函数,我们下篇文章再讨论。

你可能感兴趣的:(函数(VBA),数据库,linux,算法)