2012-08-23 4 views
14

길을 얻는 방법 중 하나. 나는 큰 800메가바이트 텍스트 파일이있는 경우 파일에서 라인의powershell 큰 (큰) 파일의 줄 수 얻기

PS C:\Users\Pranav\Desktop\PS_Test_Scripts> $a=Get-Content .\sub.ps1 
PS C:\Users\Pranav\Desktop\PS_Test_Scripts> $a.count 
34 
PS C:\Users\Pranav\Desktop\PS_Test_Scripts> 

PowerShell의이 방법은, 내가 그것에서 줄 번호를 어떻게 전체 파일을 읽지 않고, 그러나입니까?

위의 방법은 너무 많은 RAM을 소비하므로 스크립트가 손상되거나 완료하는 데 너무 오래 걸릴 수 있습니다.

답변

13

사용 Get-Content -Read $nLinesAtTime이 부분

$nlines = 0; 
#read file by 1000 lines at a time 
gc $YOURFILE -read 1000 | % { $nlines += $_.Length }; 
[string]::Format("{0} has {1} lines", $YOURFILE, $nlines) 

을하여 파일 부분을 읽어 여기에 간단하지만 느린 스크립트가 작은 파일에 대한 작업의 유효성을 검사하는

gc $YOURFILE | Measure-Object -Line 
+1

당신의 두 번째 방법은 텍스트 만 행을 계산한다는 지적 가치가있다. 빈 줄이 있으면 계산되지 않습니다. – Vladislav

8

시도하는 첫 번째 것은 Get-Content를 스트리밍하는 것입니다 한 번에 한 행씩 모든 행을 배열에 저장하는 것이 아니라 한 번에 하나씩 행 개수를 늘리십시오. 이것은 적절한 스트리밍 동작을 제공 할 것이라고 생각합니다. 즉, 전체 파일이 한 번에 메모리에 저장되지 않고 현재 줄뿐입니다.

다른 대답에서 알 수 있듯이 -ReadCount을 추가하면 속도가 빨라질 수 있습니다. 즉 당신이 StreamReader에 직접 갈 수있다 (너무 느리거나 너무 많은 메모리) 당신을 위해 작동하지 않는 경우

: 여기

$count = 0 
$reader = New-Object IO.StreamReader 'c:\logs\MyLog.txt' 
while($reader.ReadLine() -ne $null){ $count++ } 
$reader.Close() # don't forget to do this. Ideally put this in a try/finally block to make sure it happens 
+0

위의 IO.StreamReader 코드를 사용하면 아래의 gc 메서드를 사용할 때 메모리 부족 오류가 해결되었습니다. PowerShell 5.0.10514.6을 사용하여 메모리 사용량이 훨씬 적음을 확인할 수 있습니다. – Fares

1

는 밖으로 구문 분석 할 때 내가 메모리 사용을 줄이는 노력에 쓴 뭔가 내 txt 파일의 공백 문자. 그 말로는 메모리 사용량은 여전히 ​​높지만 프로세스 실행 시간은 적습니다. 파일을 배경으로 내 파일을 제공하기 위해 파일에는 2 백만 개가 넘는 레코드가 있으며 각 줄의 앞과 뒤에 모두 공백이 있습니다. 총 시간이 5 분 이상이라고 생각합니다. 서식을 개선 할 수있는 방법이 있으면 알려주십시오. 감사

$testing = 'C:\Users\something\something\test3.txt' 

$filecleanup = gci $testing 

    foreach ($file in $filecleanup) 
    { $file1 = gc $file -readcount 1000 |foreach{ $_.Trim()} 
    $file1 > $filecleanup} 
9

다음은 각 방법에 필요한 시간과 메모리와 함께 텍스트 파일에 라인을 계산하는 몇 가지 방법을 보여줍니다 내가 함께 자갈길 PowerShell 스크립트입니다. 결과 (아래)는 시간과 메모리 요구 사항에 명확한 차이가 있음을 보여줍니다. 내 테스트의 경우, ReadCount 설정을 100으로 사용하여 Get-Content를 얻은 것처럼 보였습니다. 다른 테스트에는 훨씬 더 많은 시간 및/또는 메모리 사용이 필요했습니다. 여기서 큰 파일에 대한 결과이다

Method         Count Elapsed Time  Memory Total Memory Delta 
------         ----- ------------  ------------ ------------ 
Get-Content -ReadCount 1     95365 00:00:11.1451841   45.8   0.2 
Get-Content -ReadCount 10     95365 00:00:02.9015023   47.3   1.7 
Get-Content -ReadCount 100    95365 00:00:01.4522507   59.9   14.3 
Get-Content -ReadCount 1000    95365 00:00:01.1539634   75.4   29.7 
Get-Content -ReadCount 0     95365 00:00:01.3888746   346  300.4 
Get-Content -ReadCount 1 | Measure-Object 95365 00:00:08.6867159   46.2   0.6 
Get-Content.Count       95365 00:00:03.0574433  465.8  420.1 
StreamReader.ReadLine      95365 00:00:02.5740262   46.2   0.6 

(함유 ~은 285k 라인 308 MB) :

Method         Count Elapsed Time  Memory Total Memory Delta 
------         ----- ------------  ------------ ------------ 
Get-Content -ReadCount 1     285776 00:00:36.2280995   46.3   0.8 
Get-Content -ReadCount 10     285776 00:00:06.3486006   46.3   0.7 
Get-Content -ReadCount 100    285776 00:00:03.1590055   55.1   9.5 
Get-Content -ReadCount 1000    285776 00:00:02.8381262   88.1   42.4 
Get-Content -ReadCount 0     285776 00:00:29.4240734  894.5  848.8 
Get-Content -ReadCount 1 | Measure-Object 285776 00:00:32.7905971   46.5   0.9 
Get-Content.Count       285776 00:00:28.4504388  1219.8  1174.2 
StreamReader.ReadLine      285776 00:00:20.4495721   46   0.4 

#$testFile = 'C:\test_small.csv' # 245 lines, 150 KB 
#$testFile = 'C:\test_medium.csv' # 95,365 lines, 104 MB 
$testFile = 'C:\test_large.csv' # 285,776 lines, 308 MB 

# Using ArrayList just because they are faster than Powershell arrays, for some operations with large arrays. 
$results = New-Object System.Collections.ArrayList 

function AddResult { 
param([string] $sMethod, [string] $iCount) 
    $result = New-Object -TypeName PSObject -Property @{ 
     "Method" = $sMethod 
     "Count" = $iCount 
     "Elapsed Time" = ((Get-Date) - $dtStart) 
     "Memory Total" = [System.Math]::Round((GetMemoryUsage)/1mb, 1) 
     "Memory Delta" = [System.Math]::Round(((GetMemoryUsage) - $dMemStart)/1mb, 1) 
    } 
    [void]$results.Add($result) 
    Write-Output "$sMethod : $count" 
    [System.GC]::Collect() 
} 

function GetMemoryUsage { 
    # return ((Get-Process -Id $pid).PrivateMemorySize) 
    return ([System.GC]::GetTotalMemory($false)) 
} 

# Get-Content -ReadCount 1 
[System.GC]::Collect() 
$dMemStart = GetMemoryUsage 
$dtStart = Get-Date 
$count = 0 
Get-Content -Path $testFile -ReadCount 1 |% { $count++ } 
AddResult "Get-Content -ReadCount 1" $count 

# Get-Content -ReadCount 10,100,1000,0 
# Note: ReadCount = 1 returns a string. Any other value returns an array of strings. 
# Thus, the Count property only applies when ReadCount is not 1. 
@(10,100,1000,0) |% { 
    $dMemStart = GetMemoryUsage 
    $dtStart = Get-Date 
    $count = 0 
    Get-Content -Path $testFile -ReadCount $_ |% { $count += $_.Count } 
    AddResult "Get-Content -ReadCount $_" $count 
} 

# Get-Content | Measure-Object 
$dMemStart = GetMemoryUsage 
$dtStart = Get-Date 
$count = (Get-Content -Path $testFile -ReadCount 1 | Measure-Object -line).Lines 
AddResult "Get-Content -ReadCount 1 | Measure-Object" $count 

# Get-Content.Count 
$dMemStart = GetMemoryUsage 
$dtStart = Get-Date 
$count = (Get-Content -Path $testFile -ReadCount 1).Count 
AddResult "Get-Content.Count" $count 

# StreamReader.ReadLine 
$dMemStart = GetMemoryUsage 
$dtStart = Get-Date 
$count = 0 
# Use this constructor to avoid file access errors, like Get-Content does. 
$stream = New-Object -TypeName System.IO.FileStream(
    $testFile, 
    [System.IO.FileMode]::Open, 
    [System.IO.FileAccess]::Read, 
    [System.IO.FileShare]::ReadWrite) 
if ($stream) { 
    $reader = New-Object IO.StreamReader $stream 
    if ($reader) { 
     while(-not ($reader.EndOfStream)) { [void]$reader.ReadLine(); $count++ } 
     $reader.Close() 
    } 
    $stream.Close() 
} 

AddResult "StreamReader.ReadLine" $count 

$results | Select Method, Count, "Elapsed Time", "Memory Total", "Memory Delta" | ft -auto | Write-Output 

여기 ~ 95K 라인 104메가바이트 함유 텍스트 파일에 대한 결과이다

4

다음은 Pseudothink의 게시물을 기반으로하는 한 줄짜리 프로그램입니다. 한 특정 파일 : 현재 디렉토리에서

"the_name_of_your_file.txt" |% {$n = $_; $c = 0; Get-Content -Path $_ -ReadCount 1000 |% { $c += $_.Count }; "$n; $c"} 

모든 파일 :

Get-ChildItem "." |% {$n = $_; $c = 0; Get-Content -Path $_ -ReadCount 1000 |% { $c += $_.Count }; "$n; $c"} 
+0

자세히 설명해주십시오. –

+0

르 완벽한 솔루션. –