检查文件的前 n 个字节是否在 Powershell 中是特定的

Check if the first n bytes of a file are specific in Powershell

如何将文件中的字节与值的文字数组进行比较?

$path = "C:\BinaryFile.bin"
$bytes = Get-Content -LiteralPath $path -Encoding byte -TotalCount 4 -ReadCount 4
if ($bytes -eq [0 1 2 3]) { # How to compare to expected bytes?
    Write-Output "OK: $bytes"
}

PowerShell 没有用于序列相等的 built-in 运算符,但您可以编写自己的小实用函数来满足此目的:

function Test-ArrayEquals
{
    param([array]$ReferenceArray, [array]$DifferenceArray)

    if($ReferenceArray.Length -ne $DifferenceArray.Length){
        # not same length, not equal
        return $false
    }

    for($i = 0; $i -lt $ReferenceArray.Length; $i++){
        if($ReferenceArray[$i] -ne $DifferenceArray[$i]){
            # two aligned array members were found to not be equal
            return $false
        }
    }

    # we reached the end, array values must be equal
    return $true
}

现在您可以:

if (Test-ArrayEquals -ReferenceArray @(0, 1, 2, 3) -DifferenceArray $bytes) {
    # looks good!
}

也许 compare-object。没有输出意味着相等。准确顺序的同步窗口 0。

$path = 'file'
[byte[]](0..3) | set-content $path -Encoding Byte
$bytes = Get-Content $path -Encoding byte -TotalCount 4
if (! (compare-object $bytes 0,1,2,3 -syncwindow 0)) { 
    "OK: $bytes"
}

或者进行字符串比较:

if ("0 1 2 3" -eq $bytes) {
    "OK: $bytes"
}

数组可以通过Compare-Object进行比较。这将读取文件的前四 (4) 个字节并将其与文字数组进行比较。

在 Windows PowerShell 5.1 中:

Compare-Object `
    -ReferenceObject (Get-Content -Path '.\file.txt' -Encoding Byte -TotalCount 4) `
    -DifferenceObject @(97,100,115,102) -SyncWindow 0

在 PowerShell 核心中 6.x+:

Compare-Object `
    -ReferenceObject (Get-Content -Path '.\file.txt' -AsByteStream -TotalCount 4) `
    -DifferenceObject @(97,100,115,102) -SyncWindow 0

其他答案提供了有用的解决方案,适用于 any 类型的数组。

这是一个适用于您的情况的快捷方式将数组作为字符串进行比较 ,利用 PowerShell 字符串化 数组的方式(请参阅下面的 限制 ):

if ("$bytes" -eq '1 2 3' ) { # Be sure to use *decimal* values
    Write-Output "OK: $bytes"
}

限制:

PowerShell 通过用空格连接数组的(字符串化的)元素来对数组进行字符串化;例如,$bytes = 0x1, 0x2, 0xA; "$bytes" 变成一个具有逐字值 1 2 10 的字符串(请注意如何使用数字的 十进制 表示)。

因此,通过数组的 (PowerShell) 字符串表示比较数组仅在 满足以下条件的情况下 稳健地 有效:

  • 元素具有明确的字符串表示(通常:.NET 原始类型,例如数字和字符串)

  • 没有元素的字符串表示有 嵌入 个空格。

如果元素是 strings 并且您想要区分大小写 比较它们 ,请使用 -ceq 代替 -eq


LINQ-based解法

此解决方案基于 System.Linq.Enumerable.SequenceEqual(),适用于所有类型。

请注意需要[byte[]] 强制转换 - 它会创建强类型 副本 输入数组(它们本身是 [object[]] 类型) - 按顺序为了使方法调用起作用:

if ([Linq.Enumerable]::SequenceEqual([byte[]] $bytes, [byte[]] (1, 2, 3))) {
    Write-Output "OK: $bytes"
}

警告:在这种情况下无关紧要,但通常值得注意的是,此方法在术语方面更严格 element-by-element 比较比由 Compare-Object-eq 运算符执行的 PowerShell 相等性测试:值得注意的是,字符串元素的大小写比较 敏感 默认。如果您选择 [object[]] 作为上面的转换 - 以避免需要创建数组的 副本 - 具有相同值的数字只有在它们是完全相同的类型;值得注意的是,数组文字 1, 2, 3 创建一个 [object[]] 数组,其中包含 [int] 个值,而不是 [byte] 个值。

从好的方面来说,LINQ 的使用有可能比 Compare-Object 解决方案执行得更好 - 有关详细信息,请参阅 的底部部分。