寻找更好的方式来编写CSV

时间:2016-09-12 00:49:40

标签: powershell logic export-to-csv

我编写了几个PowerShell脚本来从windows机器收集一些统计信息。第一个是关于以一定间隔收集CPU,内存使用等。哪个工作正常。我写了另一个基本上检查文件的lastaccesstime并创建一个CSV的代码,代码如下:

$dest="C:\users\Administrator\Documents\filelist.csv"
$csvdata=@()
$source="x:\"
$count=0

Get-ChildItem -Recurse $source | foreach{

$csvdata += New-Object PSObject -Property @{FileName=$_.FullName;DateAccessed=($_.LastAccessTime).ToShortDateString()}

$csvdata|Export-Csv $dest -notype

$count+=1
$count

}

好的,如果我继续向$csvdata添加内容并且仅在循环结束时导出文件,那么如果脚本因某些错误或其他原因而结束,则可能会丢失数据。所以我把它导出到循环中,如代码所示。但这也意味着$csvdata将继续增加大小,这意味着它将具有可以增长到兆字节甚至更多的内存占用。

有没有办法将这些数据转储到CSV,清空$csvdata变量而不影响结果?希望这是有道理的。

2 个答案:

答案 0 :(得分:3)

注意:您当前问题中的代码很奇怪,因为它会在每次传递时使用已经存在的所有数据覆盖文件。使用一个小数据集你可能没有注意到,但它仍然很糟糕。请继续阅读,看看你可以做些什么。

  

但这也意味着$ csvdata将继续增加大小,这意味着它的内存占用量将增长到兆字节甚至更多。

这里有几个问题。首先是您如何构建$csvdata。使用+=会破坏数组并将其重制为一个更大的元素。这是一项代价高昂的操作,会产生性能问题。您应该能够使用管道来完成您的需求(基于我们在这里看到的很少。)

Get-ChildItem -Recurse $source | foreach{

    New-Object PSObject -Property @{FileName=$_.FullName;DateAccessed=($_.LastAccessTime).ToShortDateString()} | 
        $csvdata | Export-Csv $dest -NoTypeInformation -Append

    $count+=1
    $count
}

您没有理由存储$csvdata,因此请不要这样做。继续你的另一个祸患来源。

如果您必须存储它并且您期望大数据集,请考虑使用.Net arraylist类型。 真正使用中的基本示例

$csvData  = New-Object System.Collections.ArrayList

0..9 | ForEach-Object{
    [void]($csvData.Add([pscustomobject]@{Number=$_;Even=!($_%2)}))
}

$csvData | ExportTo-Csv -NoTypeInformation
  

如果脚本因某些错误或其他原因而结束,我可能会丢失数据。

这是您提出问题的主要原因。您担心在此过程中数据丢失。我将不得不模糊地处理你的例子,但你正试图解决我认为的错误问题。您应该担心错误处理,而不是试图找到更有弹性的导出过程。

如果可能存在代码失败,您应该考虑使用try{}catch{}块以及-ErrorAction的常见cmdlet参数。如果您正在处理终止或非终止错误,两者都取决于它们。

在失败区域使用这些将阻止您的整个过程处于不完整或可疑的状态。

答案 1 :(得分:0)

我认为没有部分export-csv,但您可以将逗号分隔值作为字符串写入并将它们附加到循环内的文件中:

$dest="C:\users\Administrator\Documents\filelist.csv"
$csvdata=@()
$source="x:\"
$count=0

"FileName,DateAccessed" | Set-Content $dest

Get-ChildItem -Recurse $source | foreach{

    "$($_.FullName),$($_.LastAccessTime.ToShortDateString())" | Add-Content $dest

$count+=1
$count
}