powershell перебирает большой файл

Привет, я только что запустил powershell, и я работаю со сценарием powershell, который должен перебирать большой файл, содержащий строки, такие как "ABCD#######";"####";"@@";## ;"@@";####;#####;"@";. Что мне нужно сделать в powershell, так это перебрать этот файл, который может содержать более 20 000 строк, и взять часть информации из каждой строки и вывести ее в другой файл. У меня это работает, проблема в том, что это очень медленно, и мне было интересно, может ли кто-нибудь помочь, вот мой код.

foreach ($fileName in (ls i.gft1* | %{$_.name})){   
$fileNo=1
$STUFFCount=0
cd work
new-item flttemp$fileNo -type file -force
cat $fileName | %{$_.replace('"','')} > temp 

foreach ($line in (cat temp)){
    echo $containerCount

    if ($STUFFCount -eq 999)
    {
        $fileNo=$fileNo+1
        $STUFFCount=0
        break;
        new-item flttemp$fileNo -type file
    }
    add-content flttemp$fileNo "STUFF_START" -encoding utf8
    add-content flttemp$fileNo "STUFF"-encoding utf8
    $no=$line.split(";")[0]
    if ($line.substring("3","1") -eq "U")
    {
        add-content flttemp$fileNo "STUFF_TYPE:STUFF" -encoding utf8
    }
    else
    {
        add-content flttemp$fileNo "STUFF_TYPE:STUFF" -encoding utf8
    }
    add-content flttemp$fileNo "STUFF_NO:$no" -encoding utf8
    add-content flttemp$fileNo "STUFF_NOTO:$no" -encoding utf8
    $ISO=$line.split(";")[1]
    add-content flttemp$fileNo "STUFF_ISO:$ISO" -encoding utf8
    $weight=$line.split(";")[5]
    if ($weight -gt 0)
    {
        $weight=2.20462 * $weight
        $weight=$weight.tostring("#.##")
        add-content flttemp$fileNo "STUFF_WGT:$weight" -encoding utf8
    }
    else
    {
        add-content flttemp$fileNo "STUFF_WGT:" -encoding utf8
    }
    $weight=$line.split(";")[6]
    if ($weight -gt 0)
    {
        $weight=2.20462 * $weight
        $weight=$weight.tostring("#.##")
        add-content flttemp$fileNo "STUFF_MWGT:$weight" -encoding utf8
    }
    else
    {
        add-content flttemp$fileNo "STUFF_MWGT:" -encoding utf8
    }
    add-content flttemp$fileNo "}STUFF_END" -encoding utf8
    $STUFFCount=$STUFFCount+1
}

}

Код работает (если редактирование ничего не пропустило), просто версия kornshell завершает создание файлов flttemp$fileNo за 1 минуту, в то время как для powershell требуется 4-5 минут, что слишком медленно для того, сколько файлов нужно этому сценарию. пройти через. Мой вопрос снова: есть ли способ, который я не использую для оптимизации powershell для более быстрого чтения файлов.


person Adlis    schedule 05.12.2016    source источник


Ответы (1)


Вы можете попробовать полностью прочитать каждый файл в память, а затем поработать над этим. Это, безусловно, ускорит работу с большими файлами.

foreach ($fileName in (ls i.gft1* | %{$_.name}))
{
    $fileString = [IO.File]::ReadAllText("$filename")  # gives you one string containing whole file

    # or

    $lines = [IO.File]::ReadAllLines("$filename")   # gives a collection of strings (lines)   

    foreach ($line in $lines)
    {
        # $line is a line (string)
    } 
}   
person Asnivor    schedule 05.12.2016
comment
Я новичок в этом, поэтому не знаю, как зациклить $lines в powershell. - person Adlis; 05.12.2016
comment
Спасибо, это улучшение на 30 секунд, но все же слишком медленно для того, что мне нужно. Думаю, Powershell слишком медленный для перебора больших файлов. Я посмотрю на ReadAllText и посмотрю, смогу ли я что-нибудь с этим сделать. - person Adlis; 05.12.2016
comment
Вы, вероятно, выполняете больше работы с файловым вводом-выводом в коде, который не должен быть там. В идеале вы должны загрузить файл в память, добавить данные, которые хотите сохранить, в строку или коллекцию в памяти, а затем, когда вы закончите, записать это в файл один раз. Минимизация обращений к диску, насколько это возможно, всегда ускорит работу. - person Asnivor; 05.12.2016
comment
Таким образом, запись вывода в 1 строку с новыми строками один раз, вероятно, улучшит время правильно? - person Adlis; 05.12.2016
comment
Безусловно. На данный момент вы добавляете каждую строку, которую хотите, в файл, используя add-content, и это происходит на каждой итерации. Это будет медленно. Вы можете просто добавить к строке, которая уже была объявлена ​​вне цикла. например - $string += $contenttoadd (или $string += $contenttoadd + `n, если вам нужны новые строки). Затем вы можете использовать [IO.File]::WriteAllText() для записи этой строки в файл. - person Asnivor; 05.12.2016
comment
спасибо, я сделал что-то подобное, и у меня было одно добавление контента, и это увеличилось с 4 минут до 6 секунд для каждой итерации flttemp. - person Adlis; 05.12.2016