2011-11-15 75 views
3

当这里是我使用添加“segment99”到一个文件夹中的所有文本文件(逐个)开头的PowerShell脚本: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 GB。

我该如何解决这个问题?

回答

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 cmdlet中的编码。感谢您的支持。测试在一个大文件(> 2GB)和效果相当好(<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对象会工作,我想? – manojlds

+1

是的,'ForEach-Object'与'。{process {..}}'是一样的(基本上),但是要慢得多。当它大约是2GB时,它很重要。 –

+0

噢,这是什么'。{'这里的记号? – manojlds