问:
您好,脚本专家!我有一个包含计算机名称列表的文本文件。如何按照字母顺序对该文件进行排序?
--LR
答:
您好,LR。如果想偷懒的话,我们就会告诉您:“对不起,您不能这样做。”我们也可以就此脱身,因为Microsoft的脚本编写技术中没有一个方法能在打开文本文件后对文件进行排序。不过,嗨,“脚本专家”什么时候偷过懒呢?
噢,对了,我们是偷过几次懒,不过希望所有的人都已经忘了。不过,这次我们将向您提供一个解决办法。
虽然没有能直接对文本文件进行排序的方法,但我们可以通过执行以下操作最终达到相同的效果:1)使用FileSystemObject将文件读取到内存中;2)在内存中按照字母顺序对文件进行排序;3)使用内存中的已排序的数据替换文件现有的内容。这些操作虽然有点儿绕弯儿,但是您最后将得到一个已按照字母顺序进行排序的文本文件,而这正是您想要的结果。
为了完成此任务,我们选择使用一个断开连接的记录集。还有其他的方法能够实现此目的(比如说,冒泡排序),但是断开连接的记录集能提供更多的灵活性,且更易于讲解,尤其适合于那些曾有过数据库编程经验的用户。我们在此将向您简要介绍断开连接的记录集;若要获得有关其工作原理的详细说明,您可能需要访问ScriptingWeek2网络广播ThingstheScriptingGuysNeverToldYou(脚本专家从未告诉过您的事情)。(作为额外提供的补充信息,该网络广播还将向您说明如何使用冒泡排序对单个文件数据进行排序。)
在开始之前,我们假定您有一个与以下内容类似的文本文件,文件的每一行都有一个计算机名称:
red-ws-02
atl-ws-01
sf-ws-02
atl-ws-02
atl-ws-03
red-ws-02
sf-ws-01
如何读取这些计算机名称、对它们进行排序并接着将排序后的列表写回该文本文件呢?我们可以使用一个与以下内容类似的脚本:
ConstadVarChar=200
ConstMaxCharacters=255
ConstForReading=1
ConstForWriting=2
SetDataList=CreateObject("ADOR.Recordset")
DataList.Fields.Append"ComputerName",adVarChar,MaxCharacters
DataList.Open
SetobjFSO=CreateObject("Scripting.FileSystemObject")
SetobjFile=objFSO.OpenTextFile("C:ScriptsComputers.txt",ForReading)
DoUntilobjFile.AtEndOfStream
strLine=objFile.ReadLine
DataList.AddNew
DataList("ComputerName")=strLine
DataList.Update
Loop
objFile.Close
DataList.Sort="ComputerName"
DataList.MoveFirst
DoUntilDataList.EOF
strText=strText&DataList.Fields.Item("ComputerName")&vbCrLf
DataList.MoveNext
Loop
SetobjFile=objFSO.OpenTextFile("C:ScriptsComputers.txt",ForWriting)
objFile.WriteLinestrText
objFile.Close
首先,我们定义要创建断开连接的记录集所需要的一系列常量。(应将断开连接的记录集视为一个只存在于内存中的、与储存在磁盘驱动器上的物理数据库无关的数据库。)然后,我们使用以下这组代码来创建一个由单个字段“ComputerName”组成的断开连接的记录集:
SetDataList=CreateObject("ADOR.Recordset")
DataList.Fields.Append"ComputerName",adVarChar,MaxCharacters
DataList.Open
接下来,我们使用FileSystemObject来打开文本文件C:ScriptsComputers.txt。此时,我们准备开始对所创建的记录集进行填充。我们要执行的操作就是逐行读取该文本文件。每读取一行,我们都将使用“AddNew”方法向记录集添加一条新记录。我们将ComputerName字段的值设置为我们刚才在该文本文件中读取的行(请记住,该文本文件的各行分别表示一个计算机名称),然后使用“Update”方法将记录保存到该记录集。继续执行此操作,直至我们读取完该文本文件的每一行为止,然后我们将关闭该文件。
是的,这听起来好像工作量很大,但是正如您看到的,所有的操作只需以下几行代码:
DoUntilobjFile.AtEndOfStream
strLine=objFile.ReadLine
DataList.AddNew
DataList("ComputerName")=strLine
DataList.Update
Loop
objFile.Close
接下来,我们需要对记录集进行排序。这是使用断开连接的记录集而不使用冒泡排序或其他手动排序算法的主要好处之一。对记录集进行排序只需执行一行代码:
DataList.Sort="ComputerName"
现在我们就有了一个已排序的记录集,需要使用该记录集将数据写回文本文件。实现此目的最简单的方法就是遍历此记录集、抓取每条记录并将整个记录集保存在一个变量中。这就是下面所执行的操作:
DataList.MoveFirst
DoUntilDataList.EOF
strText=strText&DataList.Fields.Item("ComputerName")&vbCrLf
DataList.MoveNext
Loop
我们只是看一看各行记录,然后将ComputerName字段的值存储在变量strText中。请注意我们是如何执行此操作的:我们将strText的值设置为strText中的任何值加上当前ComputerName字段的值,再加上一个回车换行符(这正是vbCrLf常量所表示的)。我们将使用内存中的一个名为strText的变量来结束此操作,该变量包含以下数据:
atl-ws-01
atl-ws-02
atl-ws-03
red-ws-02
red-ws-02
sf-ws-01
sf-ws-02
最后,重新打开该文本文件(这次是为了写入)并使用“WriteLine”方法将现有的内容替换为strText的值。因为strText的值就是已排序的计算机名称列表,所以我们就完成了对C:ScriptsComputers.txt的内容按照字母顺序进行的排序。