PowerShell自定义函数返回值意外追加blockSize数值的问题
问题描述
编写PowerShell脚本将大型CSV文件分块读取后导入SQL Server时,自定义函数Get-ImportByBlock出现异常:设置$blockSize=17365时,函数内部的$completeRows变量内容正常,但调用函数后,接收返回值的$chunkToImport变量中额外追加了数值17365。
相关代码如下:
主脚本片段
#<main script> $Global:rowDelimiter = "`r`n" $Global:nextBlockStart = '' . . . #copy rows from main CSV file $chunkToImport = Get-ImportByBlock -blockSize $blockSize $rowsInChunk = ([regex]::Matches($chunkToImport,"$rowDelimiter")).count
自定义函数代码
function Get-ImportByBlock { param( [int]$blockSize ) process{ Write-Host "Reading a block of $blockSize characters from csv..." $buffer = [char[]]::new($blockSize) $streamReader.ReadBlock($buffer,0,$blockSize) $bufferString = $buffer -join '' $streamReader.DiscardBufferedData() $Global:lastRowEndLoc = $bufferString.LastIndexOf("$rowDelimiter") If ($lastRowEndLoc -le 0) { Write-Host "Error: No complete rows found." $lastRowEndLoc = 0 } $completeRows = $nextBlockStart + $($bufferString[0..$lastRowEndLoc] -join '') Write-Host "Block of $blockSize characters read. Last complete row of data ends at $lastRowEndLoc" $nextBlockStartStartLoc = $lastRowEndLoc + 2 $nextBlockStartEndLoc = $bufferString.Length $nextBlockStart = $bufferString[$nextBlockStartStartLoc..$nextBlockStartEndLoc] -join '' Write-Host "Next block will start with the with the sub-block at locations $nextBlockStartStartLoc to $nextBlockStartEndLoc" Write-Host "Rows returned: $completeRows" -ForegroundColor DarkCyan Return $completeRows } }
测试数据示例
ID | Name | Color A | Alice | Red B | Bob | Purple C | Cindy | Green
问题原因与解决方法
数值17365的来源
这个数值是$streamReader.ReadBlock()方法的返回值——该方法会返回实际读取的字符数,当文件足够大时,返回值就是你设置的$blockSize(即17365)。
PowerShell函数的process块中,所有未被捕获到变量中的命令输出,都会被自动加入到函数的返回值集合里。你当前的代码直接调用$streamReader.ReadBlock(...)却没有接收它的返回值,导致这个数值被混入了函数的返回结果;后续Return $completeRows又返回了字符串内容,最终函数返回的是一个包含数值和字符串的数组。当你把这个数组赋值给$chunkToImport时,PowerShell会隐式将数组拼接成字符串,就出现了数值追加在内容后面的现象。
解决方法
不需要调整函数的调用语法,只需要在函数内部捕获ReadBlock的返回值即可,修改这一行代码:
# 原代码 $streamReader.ReadBlock($buffer,0,$blockSize) # 修改后 $bytesRead = $streamReader.ReadBlock($buffer,0,$blockSize)
通过将返回值存入$bytesRead变量,避免它被混入函数的返回流,这样函数就只会返回你期望的$completeRows字符串内容。
内容的提问来源于stack exchange,提问作者Inflorescence
相关产品推荐
相关产品推荐

