您好,脚本专家!我有一个固定宽度的文本文件,该文件包含名字(6 个字符)、姓氏(13 个字符)和部门(9 个字符),并且它们均在同一行上。我该如何使用 ADO 来读取呢?
-- DW
答:
您好,DW。坦白地讲,我们认为您不能使用 ADO(ActiveX 数据对象)读取这样的文件。ADO 是一种和文本文件进行交互的非常好的方法(有关详细信息,请参阅文章有关文本文件的 ADO 更多知识(英文)),但是,确实,ADO 有些挑剔:它的每项设置都必须完全正确,否则就会拒绝工作。(不像脚本专家,即使所有事情都已准备就绪,他们还是会拒绝工作。)作为一种数据库技术,ADO 需要一个“结构良好”(借用 XML 领域的一个术语)的数据库;它无法直接利用您那样的文件格式并从中产生数据库。(在这种情况下,可以将您的巨行分成若干单个记录。)
但是没关系;毕竟,我们可以使用虽古老但优秀而可靠的 VBScript 来创建结构良好的数据库。我们今天要做的就是向您展示如何快速而便捷地将您的巨大数据字符串分割成单个记录。只需通过将这些单个记录(即,文本文件中的单个记录)回显到屏幕上我们就可以达到目的。不过,您可以将这些记录段写到另一个文本文件然后使用 ADO 从其中读取数据。我们只是帮您开个头,剩下的就要靠您自己了。
首先,我们假定您已拥有一个类似于下面的文本文件,该文件的字段名称和两条记录包含于同一行之上:
First Last Dept Ken Meyer Finance Pilar Ackerman HR
我们希望最后的结果同下面的显示更为相似:
First Last Dept
Ken Meyer Finance
Pilar Ackerman HR
这可能吗?当然可能:
复制代码代码如下:
Const ForReading = 1
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objFile = objFSO.OpenTextFile("C:/Scripts/Test.txt", ForReading)
strContents = objFile.ReadAll
objFile.Close
i = False
Do Until i = True
intLength = Len(strContents)
If intLength < 28 Then
Exit Do
End If
strLines = strLines & Left(strContents, 28) & vbCrLf
strContents = Right(strContents, intLength - 28)
Loop
Wscript.Echo strLines
注意:您知道您的母亲为何一直告诉您要带上帽兜或者在穿过街道的时候朝两边看吗?是的,我们脚本专家也一直告诉您在没有指定要打开的文本文件的方式的情况下是无法将其打开的:是读取、写入还是添加。一次只能执行一项操作:无法同时以读取和写入方式打开文本文件。因此需要常量 ForReading。
噢,也戴上您的帽兜。外面很冷。
接下来我们创建 FileSystemObject 的实例并使用 OpenTextFile 方法打开文件 C:/Scripts/Test.txt。我们调用 ReadAll 方法以将此文件的全部内容读取到变量 strContents 中,然后使用 Close 方法关闭文件。
之后的这行代码很短并且有些古怪:
i = False
我们立即要做的就是建立 Do 循环,该循环用 28 个字符的增量来读取文件的内容(即变量 strContents 的值)。为什么是 28 个字符?因为,在每条记录中,我们使用 6 个字符保存名字、13 个字符保存姓氏和 9 个字符保存部门。因此:
6 + 13 + 9 = 28
为了保证循环始终进行直到整个文件读取结束,我们将变量 i 设为 False,然后执行循环直到 i 等于 True:
Do Until i = True
我们发现,i 永远不会等于 True,但是别着急:我们仍可以跳出此循环,稍后就会向您显示这种神奇的功能。
在循环内部,我们首先使用 Len 函数来确定字符串 strContents 中字符的数量(对于我们的示例文件,再加上作为一条记录的标题行,共 3 条记录,每条 28 个字符,即总共 84 个字符)。然后是以下这一小段代码:
If intLength < 28 Then
Exit Do
End If
这里我们要做的就是检查字符串长度是否少于 28 个字符。如果是,则我们一定已经到达了文件的末尾。因此,我们使用 Exit Do 命令退出循环。(这就是非常了不起的脚本专家设法逃离永无休止的 Do 循环魔掌的方式!)
若长度为 28 个字符或更多,则执行下面这行代码:
strLines = strLines & Left(strContents, 28) & vbCrLf
此处我们创建一个新字符串 strLines,它将文本文件的内容分成几条单个记录,每条记录由 28 个字符及一个回车换行符 (vbCrLf) 组成。为此,我们只需将 strLine 的当前内容同字符串中的前 28 个字符(Left 函数执行的正是此操作)及 VBScript 的常量 vbCrLf 连接起来即可。第一次循环之后 strLines 结果如下:
First Last Dept
明白其工作原理了吗?
在第一行(也就是我们的第一条记录)被安全地放到变量 strLines 中之后,接着我们就要将该信息从 strContents 中删除。这就是下面的代码所要执行的操作:
strContents = Right(strContents, intLength - 28)
这次我们要使用 Right 函数从字符串末端取出 x 个字符,也就是逆向执行。那么我们所说的 x 个字符到底是什么意思?要得到 x 的值,我们需取到 strContents 的长度 (84) 然后减去 28(单个记录的长度)。得到的结果为 56 (84 - 28 = 56),因此我们从字符串的末端开始向回数 56 个字符。这表示第一次循环之后我们会得到下面这样的结果:
Ken Meyer Finance Pilar Ackerman HR
注意:是的,有其他的方法可以达到同样的目的,其中一些可能会节省一两行代码。不过,我们认为这种方法是最简单的。
正如您所见,我们所做的全部工作就是删除了第一条记录。现在准备返回循环,重复此过程。当然,这次 strContents 的长度为 56;因为我们刚刚去掉了 28 个字符。自然,这意味着我们要停止提取此数据并停止将其添加到变量 strLines 中:
Ken Meyer Finance
我们继续此过程直到删除变量 strContents 中的所有字符。此时,我们只是回显 strLines 的值:
First Last Dept
Ken Meyer Finance
Pilar Ackerman HR
如果不是一个结构良好的数据库,那我们也不知道结果会是什么样子。
如果您希望能够将数据保存到一个文本文件并可以使用 ADO 读取此数据,就按我们讲过的去做;或者也可以只使用 VBScript 的字符串处理功能来将每行分成若干单个记录。我们将决定权留给了您。