PowerShell 7.0如何计算大块读取的大文件的哈希和

PowerShell 7.0如何计算大块读取的大文件的哈希和,powershell,hash,parallel-processing,binarywriter,Powershell,Hash,Parallel Processing,Binarywriter,脚本应该复制文件并计算它们的哈希和。 我的目标是使函数只读取一次文件,而不是3次(读取\u以获取\u副本+读取\u以获取\u哈希+读取\u以获取另一个\u副本),以最小化网络负载。 所以我尝试读取一个文件块,然后计算md5哈希和,并将文件写到几个地方。 文件大小可能从100 MB到2 TB不等,甚至更大。此时不需要检查文件标识,只需要计算初始文件的哈希和 我在计算散列和时遇到了麻烦: $ifile = "C:\Users\User\Desktop\inputfile"

脚本应该复制文件并计算它们的哈希和。 我的目标是使函数只读取一次文件,而不是3次(读取\u以获取\u副本+读取\u以获取\u哈希+读取\u以获取另一个\u副本),以最小化网络负载。 所以我尝试读取一个文件块,然后计算md5哈希和,并将文件写到几个地方。 文件大小可能从100 MB到2 TB不等,甚至更大。此时不需要检查文件标识,只需要计算初始文件的哈希和

我在计算散列和时遇到了麻烦:

    $ifile = "C:\Users\User\Desktop\inputfile"
    $ofile = "C:\Users\User\Desktop\outputfile_1"
    $ofile2 = "C:\Users\User\Desktop\outputfile_2"
    
    $md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
    $bufferSize = 10mb
    $stream = [System.IO.File]::OpenRead($ifile)
    $makenew = [System.IO.File]::OpenWrite($ofile)
    $makenew2 = [System.IO.File]::OpenWrite($ofile2)
    $buffer = new-object Byte[] $bufferSize
    
    while ( $stream.Position -lt $stream.Length ) {
       
     $bytesRead = $stream.Read($buffer, 0, $bufferSize)
     $makenew.Write($buffer, 0, $bytesread) 
     $makenew2.Write($buffer, 0, $bytesread) 
    
     # I am stuck here
     $hash = [System.BitConverter]::ToString($md5.ComputeHash($buffer)) -replace "-",""      
            
            }
    
    $stream.Close()
    $makenew.Close()
    $makenew2.Close()
如何收集数据块来计算整个文件的散列

还有一个额外的问题:有可能以并行模式计算散列并写出数据吗?特别是考虑到PS版本6不支持
工作流{parallel{}


非常感谢

如果您想手动处理输入缓冲,您需要使用
TransformBlock
/
TransformFinalBlock
方法,该方法由
$md5
公开:

while($bytesRead=$stream.Read($buffer,0,$bufferSize))
{
#写入文件副本
$makenew.Write($buffer,0,$bytesread)
$makenew2.Write($buffer,0,$bytesread)
#将下一个块馈送到MD5 CSP
$null=$md5.TransformBlock($buffer,0,$bytesRead,$null,0)
}
#完成散列例程
$md5.TransformFinalBlock([字节[]]::新的(0),0,0)
#从CSP获取哈希值
$hash=[BitConverter]::ToString($md5.hash).Replace('-','')

我的目标是使函数只读取一次文件,而不是3次(读取\u作为\u副本+读取\u作为\u哈希+读取\u作为\u另一个\u副本),以最小化网络负载

我不完全确定你所说的网络负载是什么意思。如果源文件位于远程文件共享上,但新副本进入本地文件系统,则只需复制源文件一次,然后将该副本用作第二个副本的源并进行哈希计算,即可将网络负载降至最低:

$ifile=“\\remoteMachine\c$\Users\User\Desktop\inputfile”
$ofile=“C:\Users\User\Desktop\outputfile\u 1”
$ofile2=“C:\Users\User\Desktop\outputfile\u 2”
#复制远程->本地
复制项目-路径$ifile-目标$ofile
#复制本地->本地
复制项目-路径$ofile-目标$ofile2
#散列本地文件流
$md5=新对象-TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$stream=[System.IO.File]::OpenRead($ofile)
$hash=[BitConverter]::ToString($md5.ComputeHash($stream)).Replace('-','')
FWIW,直接将文件流对象传递给
$md5.ComputeHash($stream)
可能比手动缓冲输入更快

$ifile = "C:\Users\User\Desktop\inputfile"
$ofile = "C:\Users\User\Desktop\outputfile_1"
$ofile2 = "C:\Users\User\Desktop\outputfile_2"

$md5 = new-object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
$bufferSize = 1mb
$stream = [System.IO.File]::OpenRead($ifile)
$makenew = [System.IO.File]::OpenWrite($ofile)
$makenew2 = [System.IO.File]::OpenWrite($ofile2)
$buffer = new-object Byte[] $bufferSize

while ( $stream.Position -lt $stream.Length ) 
{
     $bytesRead = $stream.Read($buffer, 0, $bufferSize)
     $makenew.Write($buffer, 0, $bytesread) 
     $makenew2.Write($buffer, 0, $bytesread) 
    
     $hash = $md5.TransformBlock($buffer, 0 , $bytesRead, $null , 0)  
} 

$md5.TransformFinalBlock([byte[]]::new(0), 0, 0)
$hash = [BitConverter]::ToString($md5.Hash).Replace('-','')      
$hash
$stream.Flush()
$stream.Close()
$makenew.Flush()
$makenew.Close()
$makenew2.Flush()
$makenew2.Close()

我怎样才能确保函数只读取初始文件一次?是的,它可以工作。只是有一点输入错误,您给出了
$hash=[BitConverter]::ToString($md5)。Replace('-','')
,应该是这样的
$hash=[BitConverter]::ToString($md5.hash)。Replace('-','')
你是对的,最简单的方法是使用
复制项
获取文件哈希
但我对每个文件有3次重复读取。这两条路径都是网络存储。因此,在2TB文件的情况下,以原始格式读取相同数据三次并不是最好的方法。我尝试在一个数据块中只读取一次数据,然后将这些数据块扔给MD5和复制函数。我想它应该快一点,而不是每次为其他操作读取相同的数据。现在,我想尝试并行散列计算并写出函数。。。