Powershell 如何提高StreamReader的性能
我必须在一个大的csv中加密一个特定的列,并将其输出到一个新的csv,但是文件大小约为400万条记录 我已尝试使用streamReader而不是import-csv cmdlet 文件结构如下所示:Powershell 如何提高StreamReader的性能,powershell,csv,Powershell,Csv,我必须在一个大的csv中加密一个特定的列,并将其输出到一个新的csv,但是文件大小约为400万条记录 我已尝试使用streamReader而不是import-csv cmdlet 文件结构如下所示: date_time;msisdn;campaign_name;campaign_type;subs_status;substate_name;start_date;end_date;message_state;channel_state;amount_usage;amount_recharge;am
date_time;msisdn;campaign_name;campaign_type;subs_status;substate_name;start_date;end_date;message_state;channel_state;amount_usage;amount_recharge;amount_call_bonus;amount_call;amount_message;amount_message_bonus;amount_data;amount_data_bonus;message_date_time
2019-06-11 12:44:15;99999999;C500_VL_090619;Jun_19;PROVISIONED;null;2019-06-10;2019-06-30;NOT_SENT;NOT_SENT;1200;null;null;1200;null;null;null;null;2019-06-10 16:20:55.0
2019-06-11 12:44:15;88888888;C500_VL_090619;Jun_19;PROVISIONED;null;2019-06-10;2019-06-30;NOT_SENT;NOT_SENT;null;null;null;null;null;null;null;null;2019-06-10 16:20:55.0
2019-06-11 12:44:15;95555555;C500_VL_090619;Jun_19;PROVISIONED;null;2019-06-10;2019-06-30;NOT_SENT;NOT_SENT;null;null;null;null;null;null;null;null;2019-06-10 16:20:55.0
2019-06-11 12:44:15;35555555;C500_VL_090619;Jun_19;PROVISIONED;null;2019-06-10;2019-06-30;NOT_SENT;NOT_SENT;null;null;null;null;null;null;null;null;2019-06-10 16:20:55.0
这是我试过的代码
#################
# Powershell Allows The Loading of .NET Assemblies
# Load the Security assembly to use with this script
#################
[Reflection.Assembly]::LoadWithPartialName("System.Security")
#################
# This function is to Encrypt A String.
# $string is the string to encrypt, $passphrase is a second security "password" that has to be passed to decrypt.
# $salt is used during the generation of the crypto password to prevent password guessing.
# $init is used to compute the crypto hash -- a checksum of the encryption
#################
function Encrypt-String($String, $Passphrase, $salt="SaltCrypto", $init="IV_Password", [switch]$arrayOutput)
{
# Create a COM Object for RijndaelManaged Cryptography
$r = new-Object System.Security.Cryptography.RijndaelManaged
# Convert the Passphrase to UTF8 Bytes
$pass = [Text.Encoding]::UTF8.GetBytes($Passphrase)
# Convert the Salt to UTF Bytes
$salt = [Text.Encoding]::UTF8.GetBytes($salt)
# Create the Encryption Key using the passphrase, salt and SHA1 algorithm at 256 bits
$r.Key = (new-Object Security.Cryptography.PasswordDeriveBytes $pass, $salt, "SHA1", 5).GetBytes(32) #256/8
# Create the Intersecting Vector Cryptology Hash with the init
$r.IV = (new-Object Security.Cryptography.SHA1Managed).ComputeHash( [Text.Encoding]::UTF8.GetBytes($init) )[0..15]
# Starts the New Encryption using the Key and IV
$c = $r.CreateEncryptor()
# Creates a MemoryStream to do the encryption in
$ms = new-Object IO.MemoryStream
# Creates the new Cryptology Stream --> Outputs to $MS or Memory Stream
$cs = new-Object Security.Cryptography.CryptoStream $ms,$c,"Write"
# Starts the new Cryptology Stream
$sw = new-Object IO.StreamWriter $cs
# Writes the string in the Cryptology Stream
$sw.Write($String)
# Stops the stream writer
$sw.Close()
# Stops the Cryptology Stream
$cs.Close()
# Stops writing to Memory
$ms.Close()
# Clears the IV and HASH from memory to prevent memory read attacks
$r.Clear()
# Takes the MemoryStream and puts it to an array
[byte[]]$result = $ms.ToArray()
# Converts the array from Base 64 to a string and returns
return [Convert]::ToBase64String($result)
}
$files = Get-ChildItem ".\input\"
$infile = Get-Item .\input\test.csv
$reader = New-Object -TypeName System.IO.StreamReader -ArgumentList $infile
$allLines = @()
while ($line = $reader.ReadLine())
{
"===================Start===================="
$array = $line.split(";")
$array[1]
$array[1] = Encrypt-String $array[1].msisdn "MyStrongPassword"
$array
"====================END==================="
$b = $($array -join '";"')
$allLines += $b
}
$allLines | Out-File -FilePath .\output\outputFile.csv
$reader.close()
加密功能的功劳归于此开发人员:
但是,该文件需要1小时
有什么方法可以让它更快吗?通过不使用慢速数组连接
$allLines+=$b
并将System.IO.StreamWriter与System.IO.StreamReader一起使用,这应该更快:
$reader = New-Object System.IO.StreamReader("D:\test.csv")
$writer = New-Object System.IO.StreamWriter("D:\outputFile.csv")
# special care for the first headers line; you don't want to encrypt that
$writer.WriteLine(($reader.ReadLine()))
while (($line = $reader.ReadLine()) -ne $null) {
$fields = $line -split ';'
$fields[1] = Encrypt-String $fields[1] "MyStrongPassword"
$writer.WriteLine(($fields -join ';'))
}
$reader.Dispose()
$writer.Dispose()
根据您的代码,我推测您希望在每个字段周围添加引号。在这种情况下,请使用:
$reader = New-Object System.IO.StreamReader("D:\test.csv")
$writer = New-Object System.IO.StreamWriter("D:\outputFile.csv")
# special care for the first headers line; you don't want to encrypt that
$writer.WriteLine(('"{0}"' -f (($reader.ReadLine()) -replace ';', '";"')))
while (($line = $reader.ReadLine()) -ne $null) {
$fields = $line -split ';'
$fields[1] = Encrypt-String $fields[1] "MyStrongPassword"
$writer.WriteLine(('"{0}"' -f ($fields -join '";"')))
}
$reader.Dispose()
$writer.Dispose()
注意:这当然不会加快下载的
加密字符串
函数的处理时间。替换影响很大吗?如果我不使用引号,这会使它更快吗?@Sam-replace
只对标题行使用一次,以便在标题周围加引号。这几乎算不上是对速度的惩罚。当然,数据中每一行的引用都会对非常大的文件产生影响。您可以进行测试运行并检查最终的效果。然而,我更喜欢引用CSV,并随时接受几毫秒的额外处理时间。