计算csv文件中的记录 - Powershell

时间:2015-08-28 15:44:48

标签: powershell csv

我有以下PS脚本来计算。有没有办法计算(减去标题)而不导入整个csv?有时csv文件非常大,有时它没有记录。

Get-ChildItem 'C:\Temp\*.csv' | ForEach {
    $check = Import-Csv $_
    If ($check) { Write-Host "$($_.FullName) contains data" }
    Else { Write-Host "$($_.FullName) does not contain data" }
}

2 个答案:

答案 0 :(得分:1)

要计算行而不用担心标题,请使用:

$c = (Import-Csv $_.FullName).count

然而,这必须将整个文件读入内存。计算文件的更快方法是使用带有readcount标志的Get-Content,如下所示:

$c = 0
Get-Content $_.FullName -ReadCount 1000 | % {$c += $_.Length}
$c -= 1

要从计数中删除标题行,只需减去1.如果没有行的文件没有标题,您可以避免将它们计算为减1,如下所示:

$c = 0
Get-Content $_.FullName -ReadCount 1000 | % {$c += $_.Length}
$c -= @{$true = 0; $false = - 1}[$c -eq 0]

答案 1 :(得分:0)

以下是检查CSV文件为空的函数(如果为空则返回False,否则返回-ReadCount),具有以下功能:

  • 可以跳过标题
  • 适用于PS 2.0(PS 2.0没有Get-Content切换Test-IsCsvEmpty -FileName 'c:\foo.csv' -MaxLines 2 -NoHeader cmdlet)
  • 不在内存中加载整个文件
  • 意识到CSV文件结构(不计算空行/无效行)。

它接受以下论点:

  • FileName CSV文件的路径。
  • MaxLine 从文件中读取的最大行数。
  • NoHeader 如果未指定此开关,则函数将跳过文件的第一行

用法示例:

function Test-IsCsvEmpty
{
    Param
    (
        [Parameter(Mandatory = $true, ValueFromPipeline = $true, ValueFromPipelineByPropertyName = $true)]
        [string]$FileName,

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [ValidateRange(1, [int]::MaxValue)]
        [int]$MaxLines = 2,

        [Parameter(ValueFromPipelineByPropertyName = $true)]
        [switch]$NoHeader
    )

    Begin
    {
        # Setup regex for CSV parsing
        $DQuotes = '"'
        $Separator = ','
        # http://stackoverflow.com/questions/15927291/how-to-split-a-string-by-comma-ignoring-comma-in-double-quotes
        $SplitRegex = "$Separator(?=(?:[^$DQuotes]|$DQuotes[^$DQuotes]*$DQuotes)*$)"
    }

    Process
    {
        # Open file in StreamReader
        $InFile = New-Object -TypeName System.IO.StreamReader -ArgumentList $FileName -ErrorAction Stop

        # Set inital values for Raw\Data lines count
        $CsvRawLinesCount = 0
        $CsvDataLinesCount = 0

        # Loop over lines in file
        while(($line = $InFile.ReadLine()) -ne $null)
        {
            # Increase Raw line counter
            $CsvRawLinesCount++

            # Skip header, if requested
            if(!$NoHeader -and ($CsvRawLinesCount -eq 1))
            {
                continue
            }

            # Stop processing if MaxLines limit is reached
            if($CsvRawLinesCount -gt $MaxLines)
            {
                break
            }

            # Try to parse line as CSV
            if($line -match $SplitRegex)
            {
                # If success, increase CSV Data line counter 
                $CsvDataLinesCount++
            }
        }
    }

    End
    {
        # Close file, dispose StreamReader
        $InFile.Close()
        $InFile.Dispose()

        # Write result to the pipeline
        if($CsvDataLinesCount -gt 0)
        {
            $false
        }
        else
        {
            $true
        }
    }
}
{{1}}