应该还记得,我们曾经告诉过您:脚本专家从不对您说谎。(我们为您提供的信息可能有误,但那不是因为我们在对您说谎,而只是因为我们知道的就是那么多了!)上周我们承诺过,本次的每周测验题会比较容易,而情况也确实如此:除了可能存在一两个例外,所有提交条目的人的答案均完全正确。提示您一下:本周的测试题同样很容易。
您说对了:连续两周都是这样。我们一定感觉很轻松。
如果您未做上周的测验,不妨可以在此处试一下;您也可以继续阅读,让我们告诉您答案。不要忘了,本周我们又给出了一道新测验题。请试一试,看看您的答案会是什么。
信不信由您,这是一道甚至不用运行脚本即可解决的测验题。为什么这么说呢?是这样,我们需要对文本文件执行两个不同的操作:首先,我们需要从中读取信息,然后我们需要向其中写入信息。尽管我们需要对该文件执行两个操作,但我们只需打开该文件一次。问题就在这里。
很不幸,不,我们并非在戏弄您:确实就是这里出现了问题。不管怎样,FileSystemObject - 用于处理文本文件的脚本组件 - 并非特别完善。 例如,它的其中一个局限性就是:您可以打开一个文件并从中读取信息,或者可打开一个文件并向其中写入信息。然而,您不能同时执行这两种操作。如果需要同时从文件中读取信息和向其中写入信息,您必须:
1. | 打开文件并从中读取信息。 |
2. | 关闭文件。 |
3. | 重新打开文件并向其中写入信息。 |
4. | 关闭文件。 |
没错,这确实有些麻烦。但它的工作方式就是如此。这正是我们的脚本文件未能执行的操作。我们打开了文件并从中读取了信息,然而,随后在没有关闭文件并重新打开的情况下即试图向其中写入信息了。正如我们发现这个方法很麻烦一样,当您尝试执行类似的操作时,FileSystemObject 也不喜欢这样做。
不过,从好的方面来看,至少这是一个易于修复的脚本:
On Error Resume Next
Set objFSO = CreateObject("Scripting.FileSystemObject")
Set objTextFile = objFSO.OpenTextFile("c:\scripts\test.txt", 1)
Do Until objTextFile.AtEndOfStream
strContents = objTextFile.ReadAll
Loop
objTextFile.Close
Set objTextFile = objFSO.OpenTextFile("c:\scripts\test.txt", 2)
strContents = strContents & vbCrLf & "This line was added at the end of the file."
Wscript.Echo strContents
objTextFile.Write strContents
objTextFile.Close
正如您所看到的那样,为了修复这个脚本,我们无需做太多事情。当我们完成从文件中读取信息的操作后,我们调用了 Close 方法并关闭了文件。这是您应习以为常的操作。毕竟,在您已读取了整个文件后,就没有必要再让文件一直处于打开状态:您不仅无法向文件中写入信息,而且也无法再次从中读取信息。(要重新读取文件,您必须关闭文件并将其重新打开。)正因如此,每次读取文件后最好将其关闭。这将有助于避免与我们在这个脚本中所遇到问题相类似的一些问题。
关闭文件后,我们随后使用下面这行代码来立即重新打开文件:
Set objTextFile = objFSO.OpenTextFile("c:\scripts\test.txt", 2)
请注意此行代码与我们第一次打开文件时所用的那行代码之间的一个不同之处。OpenTextFile 方法需要以下两个参数:要打开文件的完整路径和打开该文件时应使用的“模式”。在脚本的开头,我们将数值 1 作为文件模式参数进行传递,这就意味着,文件将打开以便进行读取操作。这一次我们将数值 2 作为文件模式参数进行传递,这就意味着,文件将打开以便进行写入操作。
这是个不错的点子:有些人只是浏览一下该脚本,可能不会去想值 1 和 2 代表什么。因此,我们最好应在脚本的开头定义一对常量,然后在打开文件时使用这些常量。换句话说,我们应在脚本的适当位置插入以下四行代码:
Const ForReading = 1
Const ForWriting = 2
Set objTextFile = objFSO.OpenTextFile("c:\scripts\test.txt", ForReading)
Set objTextFile = objFSO.OpenTextFile("c:\scripts\test.txt", ForWriting)
显然,您不必这样做,不过,这样做会令您的脚本更易于阅读和理解。
当打开文件以便执行写入操作后,我们只使用 Write 方法来将文件的现有内容替换为修改后的文件内容。(我们所要做的是取出现有文件并在其末尾添加一行内容。)然后关闭文件 - 不再打开,这一次 - 大功告成。
注意:是的,我们本来可以打开文件以进行添加操作(使文件模式参数值为 8 的操作);那样做将会更容易一些。我们之所以未这样做,只是因为想尽可能多地保留原始代码。不过,如果您知道如何将数据添加到文本文件中,那么,这不失为一个非常有效的解决方案。如果您不知道如何将数据添加到文本文件中,那么您可能想阅读 Microsoft Windows 2000 Scripting Guide(英文)中的此部分内容。 |
正如我们说过的那样,如果您熟悉 FileSystemObject,那么,只要阅读一下脚本即可解答此测试题。不过,即使您从未听说过 FileSystemObject,单靠您自己也可能解决此问题。或许会很难,但并非不可能。
解决此类问题(调试脚本时,这类问题很常见)的秘诀就是注释掉 On Error Resume Next 语句。事实证明,该脚本实际上确实会生成一个错误消息;正是 On Error Resume Next 语句使得这条消息无法显示出来。以下内容即为当您注释掉 On Error Resume Next 语句后将获得的消息:
C:\Scripts\Test.vbs(15, 1) Microsoft VBScript runtime error: Bad file mode
这并不是所创建的最为直观的错误消息,不过,它确实为您提供了一些信息:您可进入搜索引擎。此错误消息 - 实际上会出现在第 15 行,在该行所在的位置,您试图向文件中写入信息 - 还应提示您:FileSystemObject 确实存在问题。出现了这样的信息,您就可以去查看 Scripting Guide(英文)或者您好,脚本专家!存档。例如,后面的存档中包含许多同处理文本文件有关的专栏,许多这样的专栏中都有下面这样的话:
“FileSystemObject 的工作方式就是如此:您可以打开文件进行读取或写入,但不能同时进行这两种操作。”
至此您已得到了答案。当然,不能保证如此,但考虑到仅 Scripting Guide 就有大约 1,300 页之多这样的事实,可以肯定地说,生活中许多(如果并非全部)问题的答案都可在某个地方(或者在您好,脚本专家!中)找到。您仅需要知道到哪里去找即可。