【问题标题】:Can't Get Powershell to assign an array over a certain size无法让 Powershell 分配超过一定大小的数组
【发布时间】:2021-02-08 23:49:29
【问题描述】:

因此,我正在尝试创建一个 powershell 脚本,该脚本使用各种大小的文件来“衡量”GPG 的速度。给我带来麻烦的具体部分是:

1 $temppath="$($env:Temp)\"
...
4 Measure-Command {$bytes= 10000MB
5 [System.Security.Cryptography.RNGCryptoServiceProvider]$rng = New- Object.System.Security.Cryptography.RNGCryptoServiceProvider
6 $rndbytes = New-Object byte[] $bytes
7 [System.Io.File]::WriteAllBytes("$($temppath)\test.txt", $rndbytes)} | Select-Object -OutVariable gentime | Out-Null; 

$bytes >~ 1.5GB(我使用 10000MB 来测试它)时,我收到一个错误,如果我正确理解发生了什么,则对应于字节数组由 int32 类型的变量索引的事实.具体错误是这样的:

New-Object : Cannot convert argument "0", with value: "10485760000", for "Byte[]" to type "System.Int32": "Cannot convert value "10485760000" to type "System.Int32". Error: "Value was either too large or too small for an Int32.""
At line:6 char:13
+ $rndbytes = New-Object byte[] $bytes
    + CategoryInfo          : InvalidOperation: (:) [New-Object], MethodException
    + FullyQualifiedErrorId : ConstructorInvokedThrowException,Microsoft.PowerShell.Commands.NewObjectCommand

有没有办法强制 powershell 在创建对象时使用 int64uint64 类型的索引来索引 $rndbytes?如果这不是问题,我很乐意被展示并解释到底出了什么问题。

请注意,如果您使用例如$bytes=1000MB(或写$bytes=1GB),则代码可以完美运行。我怀疑我在$bytes.index > 2^31 -1 左右碰壁了。

谢谢你的帮助~!!

【问题讨论】:

  • 不,数组的长度不能超过[int]::MaxValue。批量输出
  • 该死,真不幸。那么只需要创建多个数组并批量处理?
  • 创建一个小的缓冲区数组(例如 4KB),然后写入该大小的块,直到达到所需的文件大小
  • 是时候学习如何在 powershell 中做到这一点了。你知道[System.Io.File]::WriteAllBytes是覆盖数据还是追加数据?

标签: powershell types int32


【解决方案1】:

如 cmets 中所述,.NET 中的数组长度不能超过 2^31-1 项,因为数组使用的索引值为 [int] - 最大值为 2^31-1。

这并不是一个真正的问题,因为无论如何缓冲 20 亿个项目在内存中 是非常低效的 - 如果您想要 10GB 的随机数据,您可以生成并以 的形式将其写入磁盘em> 代替:

# Set file size
$intendedSize = 10GB

# Create output buffer
$buffer = [byte[]]::new(4KB)

# Create RNG
$rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::Create()

# Create temp file, open writable filestrem
$tempFile = [System.IO.Path]::GetTempFileName() |Get-Item
$fileStream = $tempFile.OpenWrite()

do {
    # Fill buffer, write to disk, rinse-repeat
    $rng.GetBytes($buffer)
    $fileStream.Write($buffer, 0, $buffer.Length)
} while($fileStream.Length -lt $intendedSize)

# Dispose if filestream + RNG
$fileStream.Dispose()
$rng.Dispose()

4KB 通常是 Windows 上一个很好的通用缓冲区大小,因为 4KB 是 NTFS 卷上的默认集群大小,并且大多数现代 CPU 的 L1 缓存大小可被 4KB 整除

【讨论】:

  • $rng = [System.Security.Cryptography.RNGCryptoServiceProvider]::Create()$rng = new [System.Security.Cryptography.RNGCryptoServiceProvider]()[System.Security.Cryptography.RNGCryptoServiceProvider]$rng = New-Object System.Security.Cryptography.RNGCryptoServiceProvider 有什么区别?老实说,我对 Powershell 很陌生,在此之前我只将它用于非常基本的事情。另外,Powershell 与 C# 非常相似吗?看起来是这样,如果是的话,我可能只是学习使用 C# 作为一种补充我的 Powershell 能力的方法
  • @Shinaolord $rng = new [TypeName]() 不是有效的 PowerShell。 New-Object TypeName 本质上与[TypeName]::new() 相同,但由于RNGCryptoServiceProvider 暴露了一个静态的Create() 方法,作者可能打算让用户使用它 - 所以这就是我使用的:-) PowerShell 共享相同的底层基础C# 类库 (.NET) 和一些语法元素大量“借用”自 C#,但它们是两种不同的语言。
  • 当我查看 Microsoft 的 RNGCryptoServiceProvider 文档页面时,我只是没有看到 ::Create() 方法,所以我不确定(:。我真的只知道 Mathematica 而不太了解 matlab,并且涉足 C++ 和 Python,但我对这些语言一窍不通。感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 2021-07-11
  • 1970-01-01
  • 2012-12-20
  • 1970-01-01
  • 1970-01-01
  • 2021-12-02
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多