Pet*_*hia 9 powershell etl text-files
我正在使用Powershell进行一些ETL工作,读取压缩文本文件并根据每行的前三个字符将它们拆分.
如果我只是过滤输入文件,我可以将过滤后的流传输到Out-File并完成它.但我需要将输出重定向到多个目标,据我所知,这不能用简单的管道完成.我已经在使用.NET流读取器来读取压缩的输入文件了,我想知道是否需要使用一个streamwriter来编写输出文件.
天真的版本看起来像这样:
while (!$reader.EndOfFile) {
$line = $reader.ReadLine();
switch ($line.substring(0,3) {
"001" {Add-Content "output001.txt" $line}
"002" {Add-Content "output002.txt" $line}
"003" {Add-Content "output003.txt" $line}
}
}
Run Code Online (Sandbox Code Playgroud)
这看起来像坏消息:每行查找,打开,写入和关闭文件一次.输入文件是巨大的500MB +怪物.
是否有一种惯用的方法来处理这个有效的Powershell构造,或者我应该转向.NET编写器?
是否有我可以使用的(New-Item"path"-type"file")对象的方法?
编辑上下文:
我正在使用DotNetZip库将ZIP文件作为流读取; 因此streamreader
而不是Get-Content
/ gc
.示例代码:
[System.Reflection.Assembly]::LoadFrom("\Path\To\Ionic.Zip.dll")
$zipfile = [Ionic.Zip.ZipFile]::Read("\Path\To\File.zip")
foreach ($entry in $zipfile) {
$reader = new-object system.io.streamreader $entry.OpenReader();
while (!$reader.EndOfFile) {
$line = $reader.ReadLine();
#do something here
}
}
Run Code Online (Sandbox Code Playgroud)
我应该Dispose()
同时使用$ zipfile和$ reader,但这是另一个问题!
ste*_*tej 14
至于阅读文件和解析,我会switch
说:
switch -file c:\temp\stackoverflow.testfile2.txt -regex {
"^001" {Add-Content c:\temp\stackoverflow.testfile.001.txt $_}
"^002" {Add-Content c:\temp\stackoverflow.testfile.002.txt $_}
"^003" {Add-Content c:\temp\stackoverflow.testfile.003.txt $_}
}
Run Code Online (Sandbox Code Playgroud)
我认为这是更好的方法,因为
-file
非常方便;)至于编写输出,我将测试使用streamwriter,但是如果性能Add-Content
对你来说不错,我会坚持下去.
补充:Keith建议使用>>
运算符,但是,它似乎很慢.除此之外,它以Unicode编写输出,使文件大小加倍.
看看我的测试:
[1]: (measure-command {
>> gc c:\temp\stackoverflow.testfile2.txt | %{$c = $_; switch ($_.Substring(0,3)) {
>> '001'{$c >> c:\temp\stackoverflow.testfile.001.txt} `
>> '002'{$c >> c:\temp\stackoverflow.testfile.002.txt} `
>> '003'{$c >> c:\temp\stackoverflow.testfile.003.txt}}}
>> }).TotalSeconds
>>
159,1585874
[2]: (measure-command {
>> gc c:\temp\stackoverflow.testfile2.txt | %{$c = $_; switch ($_.Substring(0,3)) {
>> '001'{$c | Add-content c:\temp\stackoverflow.testfile.001.txt} `
>> '002'{$c | Add-content c:\temp\stackoverflow.testfile.002.txt} `
>> '003'{$c | Add-content c:\temp\stackoverflow.testfile.003.txt}}}
>> }).TotalSeconds
>>
9,2696923
Run Code Online (Sandbox Code Playgroud)
差异很大.
仅供比较:
[3]: (measure-command {
>> $reader = new-object io.streamreader c:\temp\stackoverflow.testfile2.txt
>> while (!$reader.EndOfStream) {
>> $line = $reader.ReadLine();
>> switch ($line.substring(0,3)) {
>> "001" {Add-Content c:\temp\stackoverflow.testfile.001.txt $line}
>> "002" {Add-Content c:\temp\stackoverflow.testfile.002.txt $line}
>> "003" {Add-Content c:\temp\stackoverflow.testfile.003.txt $line}
>> }
>> }
>> $reader.close()
>> }).TotalSeconds
>>
8,2454369
[4]: (measure-command {
>> switch -file c:\temp\stackoverflow.testfile2.txt -regex {
>> "^001" {Add-Content c:\temp\stackoverflow.testfile.001.txt $_}
>> "^002" {Add-Content c:\temp\stackoverflow.testfile.002.txt $_}
>> "^003" {Add-Content c:\temp\stackoverflow.testfile.003.txt $_}
>> }
>> }).TotalSeconds
8,6755565
Run Code Online (Sandbox Code Playgroud)
补充:我对写作表现很好奇......我有点惊讶
[8]: (measure-command {
>> $sw1 = new-object io.streamwriter c:\temp\stackoverflow.testfile.001.txt3b
>> $sw2 = new-object io.streamwriter c:\temp\stackoverflow.testfile.002.txt3b
>> $sw3 = new-object io.streamwriter c:\temp\stackoverflow.testfile.003.txt3b
>> switch -file c:\temp\stackoverflow.testfile2.txt -regex {
>> "^001" {$sw1.WriteLine($_)}
>> "^002" {$sw2.WriteLine($_)}
>> "^003" {$sw3.WriteLine($_)}
>> }
>> $sw1.Close()
>> $sw2.Close()
>> $sw3.Close()
>>
>> }).TotalSeconds
>>
0,1062315
Run Code Online (Sandbox Code Playgroud)
它快80倍.现在您必须决定 - 如果速度很重要,请使用StreamWriter
.如果代码清晰度很重要,请使用Add-Content
.
根据Keith Substring的速度提高了20%.这一直取决于它.但是,就我而言,结果是这样的:
[102]: (measure-command {
>> gc c:\temp\stackoverflow.testfile2.txt | %{$c = $_; switch ($_.Substring(0,3)) {
>> '001'{$c | Add-content c:\temp\stackoverflow.testfile.001.s.txt} `
>> '002'{$c | Add-content c:\temp\stackoverflow.testfile.002.s.txt} `
>> '003'{$c | Add-content c:\temp\stackoverflow.testfile.003.s.txt}}}
>> }).TotalSeconds
>>
9,0654496
[103]: (measure-command {
>> gc c:\temp\stackoverflow.testfile2.txt | %{$c = $_; switch -regex ($_) {
>> '^001'{$c | Add-content c:\temp\stackoverflow.testfile.001.r.txt} `
>> '^002'{$c | Add-content c:\temp\stackoverflow.testfile.002.r.txt} `
>> '^003'{$c | Add-content c:\temp\stackoverflow.testfile.003.r.txt}}}
>> }).TotalSeconds
>>
9,2563681
Run Code Online (Sandbox Code Playgroud)
所以区别并不重要,对我来说,正则表达式更具可读性.
归档时间: |
|
查看次数: |
5696 次 |
最近记录: |