寻找一种更好的方式来编写 CSV

Looking for a better way to write CSVs

我编写了几个 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 变量而不影响结果?希望这是有道理的。

我认为没有部分 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
}

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

But this also means the $csvdata will keep increasing in size and that means it will have a memory footprint which can grow to be megabytes or even more.

这里有几个问题。首先是您的构建方式 $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

there is a possibility I might lose data if script ends due to some error or something.

这似乎是您提出问题的主要原因。您担心在此过程中数据丢失。我将不得不含糊地处理您的示例,但您正在尝试解决我认为的错误问题。与其尝试寻找更具弹性的导出过程,不如担心错误处理。

如果存在代码失败的可能性,您应该考虑使用 try{}catch{} blocks as well as the common cmdlets parameter for -ErrorAction。两者都有自己的位置,具体取决于您是在处理终止错误还是非终止错误。

在失败的区域使用这些将防止您的整个过程处于不完整或有问题的状态。