【问题标题】:StreamWriter - Process cannot access the file because it is being used by another processStreamWriter - 进程无法访问该文件,因为它正被另一个进程使用
【发布时间】:2017-05-09 06:31:09
【问题描述】:

我正在尝试将 Add-Content 脚本重写为 StreamWriter 版本,原因是文件约为 140 MB,而 Add-Content 太慢了。

这是我的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)
}

我认为这与在我的循环中使用它有关。

样本数据:

文件|数据文件 1|25/04/17 25044|0001|37339|10380|TT75 25045|0001|37339|10398|TT75 25046|0001|78711|15940|TT75 文件|数据文件 2|25/04/17 25047|0001|98745|11263|TT75 25048|0001|96960|13011|TT84 文件|数据文件 3|25/04/17 25074|0001|57585|13639|TT84 25075|0001|59036|10495|TT84 文件|数据文件 4|25/04/17 25076|0001|75844|13956|TT84 25077|0001|17430|01111|TT84

期望的结果是每个 FILE| 标题行 1 个文件,使用第二个分隔值作为文件名。

【问题讨论】:

  • 嗨,$sw = New-Object System.IO.StreamWriter (Join-Path $Path $OutputFile) 不应该是 before while 循环,而不是 inside 它吗?

标签: powershell


【解决方案1】:

您正在 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|... 行开头,输入文件为空等)。你可能想改变它。

【讨论】:

  • 感谢您的回答。将 write before 循环运行脚本,但不会模仿 Add-Content 行为。它只是在第一次点击FILE| 后写入全部内容,并忽略以FILE| 开头的其他标题行。关于为什么的任何想法?
猜你喜欢
  • 2021-12-11
  • 1970-01-01
  • 2014-12-10
  • 2010-12-10
相关资源
最近更新 更多