Import-CSV слишком медленно

В настоящее время у меня есть сценарий PowerShell, который импортирует файл CSV, а затем фильтрует 1-й столбец, чтобы удалить всю строку, если строка превышает определенное время. Однако использование Import-Csv занимает очень много времени. Есть ли другой способ добиться того же результата без использования Import-Csv?

Вот сценарий на данный момент:

$files = Get-ChildItem "C:\Results\*.csv"

foreach ($file in $files) {
    $filename = [IO.Path]::GetFileNameWithoutExtension($file)
    $csv = Import-Csv $file

    $dateTime = $csv[0]."Date and Time"

    $startTime = $dateTime.Substring($dateTime.get_Length()-8)

    $endTime = $startTime
    [int]$hour, [int]$min, [int]$sec = $endTime.Split(':')

    $hour = $hour + 1
    $min = 44
    $sec = 59

    $csv | ForEach-Object {
        $lineTime = $_."Date and Time"
        $startTime = $lineTime.Substring($lineTime.get_Length()-8)
        $newHour, $newMin, $newSec = $startTime.Split(':')
        if (($newHour -lt $hour -and $newMin -gt $min) -or ($newHour -eq $hour -and $newMin -le $min)) {
            $_ | Export-Csv -Path "C:\PerfResults\NewFiles\$filename-NEW.csv" -Append 
        }
    }
}

РЕДАКТИРОВАТЬ:

По просьбе Олафа ниже приведен пример данных в файле CSV:

Date and Time   Memory Overcommit (1 Minute Avg)    Memory Overcommit (5 Minute Avg)    Memory Overcommit (15 Minute Avg)   Cpu Load (1 Minute Avg) Cpu Load (5 Minute Avg) Load (15 Minute Avg)    Physical Cpu(0)\% Processor Time
07/24/2018 14:45:03 0   0   0   0.11    0.13    0.11    7.31
07/24/2018 14:45:06 0   0   0   0.11    0.13    0.12    1.41

person DaleSE    schedule 13.09.2018    source источник
comment
Вы также можете опубликовать несколько строк вашего файла csv (пожалуйста, отформатируйте его как код ;-)). Вероятно, это ускорит ваш код, если вы сначала соберете результаты в настраиваемый объект, а в конце экспортируете все вместе. Использование -Append очень медленно из-за необходимости внутренней работы файловой системы.   -  person Olaf    schedule 13.09.2018
comment
Спасибо за ответ, Олаф, файлы csv, с которыми я работаю, содержат ~ 12500 столбцов и 1800 строк, поэтому размещение строк может быть немного затруднительным.   -  person DaleSE    schedule 13.09.2018
comment
Поэтому вам следует сократить строки до соответствующих столбцов и выбрать из них 3 или 4 строки. И, конечно же, при необходимости вы должны скрыть конфиденциальную информацию.   -  person Olaf    schedule 13.09.2018
comment
Я приложил пример даты, содержащейся в файле, не знаю, как изменить формат, чтобы каждая запись данных отображалась под именем столбца.   -  person DaleSE    schedule 13.09.2018
comment
Не волнуйтесь - все в порядке. Дайте мне несколько минут, пожалуйста. ;-)   -  person Olaf    schedule 13.09.2018
comment
Нет проблем, спасибо, что нашли время разобраться в этом :)   -  person DaleSE    schedule 13.09.2018
comment
12500 столбцов в CSV - безумие. Почему вы используете CSV вместо базы данных для хранения этих данных?   -  person Ansgar Wiechers    schedule 13.09.2018


Ответы (1)


Когда вы имеете дело с объектами DateTime, вы должны поступать с ними как с таковыми. Вы можете вычислить или даже сравнить их намного проще, чем строки. Думаю, это сделает вашу жизнь намного проще. Это будет быстрее, если вы сначала соберете все необходимые данные, а затем сохраните их в файл за один раз.

$fileList = Get-ChildItem "C:\Results\*.csv"

foreach($file in $fileList) {
    $csv = Import-CSV -Path $file.FullName -Delimiter "`t"
    $NewData = foreach($Data in $csv){
        $Data |
            Select-Object -Property *,
                                    @{
                                        Name = 'NewDateAndTime';
                                        Expression = {
                                            $DateTime = [DateTime]::ParseExact($($Data.'Date and Time'),"MM/dd/yyyy HH:mm:ss",$null)
                                            $DateTime.AddHours(-4)
                                        }
                                    }
    }
    $NewData | Export-Csv -Path "C:\PerfResults\NewFiles\$($file.BaseName)-NEW.csv" -Delimiter "`t" -NoTypeInformation -Force
}

Если вам не нужны все данные из входного CSV в выходном CSV, вы можете выбрать те, которые вам нужны, с помощью Select-Object.

Изменить: дополнительное объяснение - я преобразовал "строковую" дату и время из файла csv в объект DateTime с вычисляемым свойством. Затем я просто вычел 4 часа, чтобы показать, как производить вычисления с DateTime объектами. Конечно, вы должны адаптировать его к вашим особым потребностям. ;-)

person Olaf    schedule 13.09.2018
comment
Спасибо за ваш ответ. Файлы теперь создаются намного быстрее, однако предоставленный вами сценарий не соответствует форматированию, создаваемому моим исходным сценарием. В вашем скрипте кажется, что все данные записываются в первый столбец, а затем только в 4 строки, вместо того, чтобы разделять каждую запись данных на отдельные ячейки. Есть идеи, как этого избежать? - person DaleSE; 13.09.2018
comment
упс ... ты прав. Я забыл -Delimiter. Я исправил код в своем ответе. Попробуй это сейчас. Я обычно использую запятую в качестве разделителя ... - person Olaf; 13.09.2018
comment
Теперь, когда я добавил разделитель к этому сценарию и формат верен, нет никакой разницы во времени, необходимом для обработки файла. Создание -NEW CSV-файла все еще занимает ~ 4 минуты. Есть ли альтернатива использованию Import-CSV? Возможно ли получение содержимого? - person DaleSE; 13.09.2018
comment
хммм ... 4 минуты примерно на 12500 столбцов и 1800 строк мне не так уж плохо. ;-) Имеет ли это значение? Придется ли его ждать или он может работать сам по себе в фоновом режиме? - person Olaf; 13.09.2018
comment
Если возможно, я хотел бы завершить процесс быстрее, у меня есть 100 файлов для обработки, и это только первый фильтр, который мне нужно выполнить, после удаления строк времени, которые мне не нужны, мне также нужно удалить столбцы из файла. - person DaleSE; 13.09.2018
comment
Это то, что я имел в виду раньше. Вы можете выполнить необходимые манипуляции в одном большом фрагменте внутри цикла, а затем записать завершенные данные один раз в новый файл. - person Olaf; 13.09.2018
comment
Спасибо за помощь! Я попробую сейчас. - person DaleSE; 13.09.2018