2017-05-08 38 views
3

我正在嘗試將Add-Content腳本重寫爲StreamWriter版本,原因是該文件大約140 MB和Add-Content太慢了。StreamWriter - 進程無法訪問文件,因爲它正在被另一個進程使用

這是我的Add-Content版本,它循環遍歷每一行,直到找到一個起始於FILE|的標題行,並創建一個新文件,該文件的第二個分隔(按管道)值在該行中。 Add-Content按預期工作,但速度很慢。這需要35-40分鐘,做到這一點:

Param(
    [string]$filepath = "\\fileserver01\Transfer", 
    [string]$filename = "sourcedata.txt" 
) 

$Path = $filepath 
$InputFile = (Join-Path $Path $filename) 
$Reader = New-Object System.IO.StreamReader($InputFile) 

while (($Line = $Reader.ReadLine()) -ne $null) { 
    if ($Line -match 'FILE\|([^\|]+)') { 
     $OutputFile = "$($matches[1]).txt" 
    } 
    Add-Content (Join-Path $Path $OutputFile) $Line 
} 

我研究的是StreamWriter應該會更快。這是我的嘗試,但我得到錯誤

進程無法訪問文件'\ fileserver01 \ Transfer \ datafile1.txt',因爲它正在被另一個進程使用。

Param(
    [string]$filepath = "\\fileserver01\Transfer", 
    [string]$filename = "sourcedata.txt" 
) 

$Path = $filepath 
$InputFile = (Join-Path $Path $filename) 
$Reader = New-Object System.IO.StreamReader($InputFile) 

while (($Line = $Reader.ReadLine()) -ne $null) { 
    if ($Line -match 'FILE\|([^\|]+)') { 
     $OutputFile = "$($matches[1])" 
    } 
    $sw = New-Object System.IO.StreamWriter (Join-Path $Path $OutputFile) 
    $sw.WriteLine($line) 
} 

我認爲這件事情做在我的循環使用。

樣本數據:

 
FILE|datafile1|25/04/17 
25044|0001|37339|10380|TT75 
25045|0001|37339|10398|TT75 
25046|0001|78711|15940|TT75 
FILE|datafile2|25/04/17 
25047|0001|98745|11263|TT75 
25048|0001|96960|13011|TT84 
FILE|datafile3|25/04/17 
25074|0001|57585|13639|TT84 
25075|0001|59036|10495|TT84 
FILE|datafile4|25/04/17 
25076|0001|75844|13956|TT84 
25077|0001|17430|01111|TT84 

期望的結果是使用所述第二分隔值作爲文件名每FILE| 1文件heade行。

+1

嗨,不應該'*在* while循環之前,而不是*內部*它是?*之前*不是新的對象System.IO.StreamWriter(加入路徑$路徑$ OutputFile)? – sodawillow

回答

2

要創建的作家while循環而沒有將其關閉,這樣你的代碼試圖重新打開與每個迭代已經打開輸出文件。關閉現有的作家,並打開一個新的,只要您的文件名更改:

while (($Line = $Reader.ReadLine()) -ne $null) { 
    if ($Line -match 'FILE\|([^\|]+)') { 
     if ($sw) { $sw.Close(); $sw.Dispose() } 
     $sw = New-Object IO.StreamWriter (Join-Path $Path $matches[1]) 
    } 
    $sw.WriteLine($line) 
} 
if ($sw) { $sw.Close(); $sw.Dispose() } 

注意,這裏假設你一定不會打開同一個文件。如果輸入文件中可能出現多次相同的輸出文件,則需要打開該文件進行追加。在這種情況下,更換

$sw = New-Object IO.StreamWriter (Join-Path $Path $matches[1]) 

$sw = [IO.File]::AppendText((Join-Path $Path $matches[1])) 

還要注意的是,代碼沒有任何錯誤處理(例如輸入文件不具有FILE|...行開始,輸入文件是空的,等)。你可能想改變它。

+0

感謝您的回答。將write before循環運行腳本,但不會模仿「Add-Content」行爲。它只是在第一次命中'FILE |'後寫入整個內容,並忽略其他開始'FILE |'的標題行。任何想法爲什麼? – TJB

+0

現貨 - 非常感謝 – TJB

相關問題