我正在VB中编写WSH脚本,以通过.Run方法读取通过重定向目录列表生成的大量目录列表。
目录列表大约是8400行,但每次运行脚本时,都会出现以下循环
直到DirList.AtEndOfStream Redim Preserve arrData(i) arrData(i)= DirList.ReadLine i = i + 1 环
早期削减,看似随机范围为1800至3500行。这听起来像是数组大小问题还是shell内存限制?
我听说有人解析LARGE日志文件,就像我一样把它们全部读出来。
答案 0 :(得分:4)
在这种情况下,首先循环访问文件并计算行数,然后将数组重命名为所需的确切大小,这样会不会更好。然后关闭文件再次打开它,这次实际将行分配给数组元素?
答案 1 :(得分:2)
VBScript中数组的大小受到一些不同的限制,以先到者为准:
最多(2 ^ 31) - 1个元素(因为元素的数量在内部存储为Long
值,并且因为没有更大的数据类型可用作索引器)
最多60个维度。
可用的系统内存。
然而,除了纯粹的理论练习之外,大多数这些限制都没有用,而且我对任何必须关注它们的代码都非常怀疑。
因为你说你只有8400行要处理,我怀疑你是否遇到了对数组大小的理论限制。相反,代码的最大问题在于您在循环中使用Redim Preserve
。
MSDN reference解释了Redim Preserve
用于动态调整数组的最后一个维度,同时保留其现有内容。它不一定提到它是如何工作的。每次使用Redim Preserve
时,都会创建一个新数组,其中包含您指定的元素数,并将前一个数组中元素的值复制到新数组中。这应该立即发送红色标记,因为这意味着在循环的每次迭代中,您为全新数组分配空间。在循环中进行的迭代次数越多,问题就越严重,因为创建的每个新数组的大小都会逐渐增大。
因此,您更有可能溢出VBScript为局部变量分配的堆栈空间。 (多么合适 - 堆栈溢出错误?)最终这些未使用的数组将被垃圾收集,但是当你在紧密循环中执行此操作时,你会对内存和资源施加巨大的压力。
您只需在阵列中分配足够的空间来容纳您需要保存的所有目录列表,这样做会好得多。您不一定必须完全正确地获得最大尺寸。简单地分配比您需要的更多仍然比不断创建和销毁新阵列便宜得多。如果您仍然担心这还不够,可以检查循环中当前索引是否大于数组中元素的最大数量,如果是,则分配更多空间(例如,加倍目前的规模)。完成后,您可以使用Redim Preserve
命令释放多余空间,同时保留好数据,但这次只有一次!对于一个粗略的打击示例:
Dim MyData() ''#declare the array
Dim MaxSize = 10000 ''#guess an initial size
Redim MyData(MaxSize) ''#allocate an array of the initial size
Dim Size
Do Until DirList.AtEndOfStream
Size = Size + 1 ''#record the current index
If Size > MaxSize Then
''#The array is full, so allocate more space
MaxSize = MaxSize * 2 ''#determine a new size (doubling is a good guess)
Redim Preserve MyData(MaxSize) ''#add more space in the array
End If
MyData(Size) = DirList.ReadLine ''#store this data in the array
Loop
If Size < MaxSize Then
Redim Preserve MyData(Size) ''#deallocate the extra space in your array
End If
这可能会使您的内存免于滥用数组的常量分配和释放。
答案 2 :(得分:0)
在循环内部使用ReDim Preserve是一种很好的做法。这是在VBScript中动态调整数组大小的唯一方法,Microsoft自己的示例代码始终执行此操作。我亲自完成了成千上万次迭代的数组,没有问题。
您遇到的问题是您的系统资源不足。在每次迭代时分配一个新数组,然后释放旧数组。问题是名义上的,在大多数情况下完全可以忽略不计。
您必须记住,您的脚本是在可执行环境中执行的。对于WSH,这意味着您的所有操作都在单个线程中执行。 WSH不提供在脚本中管理内存使用的任何方法。
我能给你的最好的建议是限制迭代次数或以块的形式读取输入文件(在每次迭代时释放它们)。如果没有看到导致错误的文件,或者您收到了实际的错误消息,我就无法提供更直接的建议。我只能说这种情况不会经常出现,而且几乎总是指向机器配置不佳或代码写得不好。