2011-11-15 2 views
3

Вот сценарий PowerShell, я использую, чтобы добавить «segment99» в начале всех текстовых файлов (один за другим) в пределах папки:OutOfMemoryException при запуске мой PowerShell сценарий

Set Environmental Variables: 

$PathData = '<<ESB_Data_Share_HSH>>\RwdPnP' 

Go to each text file in the specified folder and add header to the file: 

Get-ChildItem $PathData -filter 'test_export.txt'|%{ 

$content = '"segment99" ' + [io.file]::ReadAllText($_.FullName) 
[io.file]::WriteAllText(($_.FullName -replace '\.txt$','_99.txt'),$content) 

} 

Это дает мне следующая ошибка:

Error: Exception calling "ReadAllText" with "1" argument(s): "Exception of type 'Syste 
Error: m.OutOfMemoryException' was thrown." 
Error: At D:\apps\MVPSI\JAMS\Agent\Temp\JAMSTemp13142.ps1:17 char:51 
Error: + $content = '"segment99" ' + [io.file]::ReadAllText <<<< ($_.FullName) 
Error:  + CategoryInfo   : NotSpecified: (:) [], MethodInvocationException 
Error:  + FullyQualifiedErrorId : DotNetMethodException 
Error: 

Я запускаю этот код в папке с 20 файлами, каждая по 2 ГБ.

Как это исправить?

ответ

3

Копирование заголовка файла + большой файл в новый файл будет менее склонен к OutOfMemory исключений (для файлов такого размера):

$header = '"segment99"' 
$header | out-file header.txt -encoding ASCII 
$pathdata = "." 
Get-ChildItem $PathData -filter 'test_export.txt' | %{ 
    $newName = "{0}{1}{2}" -f $_.basename,"_99",$_.extension 
    $newPath = join-path (split-path $_.fullname) $newname 
    cmd /c copy /b "header.txt"+"$($_.fullname)" "$newpath" 
} 
+0

Вы попробовали? Он делает что-то, но не то, что нужно ... –

+1

@RomanKuzmin Я забыл кодировку в командлете out-file. Спасибо, что поймали. Протестировано в большом файле (> 2 ГБ) и работает достаточно хорошо (<1 мин.) –

+2

Чтобы быть ясным, кодировка файла заголовка должна соответствовать кодировке файла test_export.txt. –

2

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

Get-ChildItem $PathData -Filter 'test_export.txt' | %{ 
    $header = $true 
    Get-Content $_.FullName | .{process{ 
     if ($header) { 
      '"segment99" ' + $_ 
      $header = $false 
     } 
     else { 
      $_ 
     } 
    }} | Set-Content ($_.FullName -replace '\.txt$', '_99.txt') 
} 
+1

Это то, о чем я думал, предлагая. Во всяком случае, почему '. {Process {' line? Предположим, будет работать объект foreach-object? – manojlds

+1

Да, 'ForEach-Object' является тем же (в основном) как'. {Process {..}} ', но намного медленнее. Когда это около 2 ГБ, это имеет значение. –

+0

О, что это?. {'Обозначение здесь? – manojlds

Смежные вопросы