Байты Powershell в битовый массив

У меня проблема с превращением ByteArrays в биты и затем возвращением их обратно. В конце концов я пытаюсь перейти от ByteArray к Hex, а затем обратно, но у меня возвращаются значения, отличные от того, что я вставляю.

Это установка BitArray:

$list = @(1,7,10,11,13,14,15,16,17,18,19,20,21,22,23,29,30,32,33,37,39,41,42,43,44,46,48,49,54,56,60,69,72,74,77,79,88,98,100,102,104,109,114,116,118,119,120,127,128,129,133,135,143,147)
$BitArray = New-Object BitArray(152)
$list | % {$BitArray[$_ - 1] = $true}

Примечание: я использую некоторые пользовательские ускорители типов

if ($(try{[accelerators]}catch{"nope"}) -eq "nope"){
  $xlr=[psobject].Assembly.GetType('System.Management.Automation.TypeAccelerators')
  $xlr::Add('accelerators',([psobject].Assembly.GetType('System.Management.Automation.TypeAccelerators')))
}
@{
  "datatable"="System.ComponentModel.MarshalByValueComponent"
  "marshal"="System.Runtime.InteropServices.Marshal"
  "BitArray"="System.Collections.BitArray"
}.GetEnumerator() | %{
  $AcceleratorName=$_.name
  $AcceleratorValue=$_.value
  if (-not ((([accelerators]::get).keys | ? {$_ -eq "$AcceleratorName"} | Measure-Object).count)){
    [accelerators]::add("$AcceleratorName","$AcceleratorValue")
  }
}

Основываясь на том, что я нашел, я использовал это для преобразования в байты:

$result =  New-Object System.Byte[] (19)
$BitArray.CopyTo($result, 0)

Но когда я превращаю их обоих в струны, они не совпадают.

Ввод в строковый код:

$array = @()
0..151 | % {if ($BitArray[$_]) {$array += 1} else {$array += 0}}

$InputAsArray = @()
0..18 | % {
    $InputAsArray += ($array -join "").Substring(($_ * 8),8)
}

Вывод в строковый код:

($result | % { [Convert]::ToString($_, 2).PadRight(8,'0')})

Шаблон ввода:

10000010
01101111
11111110
00001101
10001010
11110101
10000101
00010000
00001001
01001010
00000001
00000000
01010101
00001000
01010111
00000011
10001010
00000010
00100000

Выходной шаблон:

10000010
11110110
11111110
10110000
10100010
10101111
10100001
10000000
10010000
10100100
10000000
00000000
10101010
10000000
11101010
11000000
10100010
10000000
10000000

1 ответ

Вот еще один способ сделать это, используя split с регулярным выражением. После этого заявления:

$List | % {$BitArray[$_ - 1] = $True}

Создать другой массив (или строку) с единицами и нулями

0..($BitArray.Count -1) | % {if ($BitArray[$_]) {$strBitArray += @("1")} else {$strBitArray += @("0")}}

Используйте регулярное выражение, чтобы разбить строку на 8-битные куски:

$ByteArray = $strBitArray  -join('') -split '(?<=\G[01]{8})(?=.)' | %{[convert]::ToInt64($_,2)}

В настоящее время есть две проблемы с вашим кодом.

Как намекнул @PetSerAl, BitArray.CopyTo() кажется, чтобы изменить порядок / порядок байтов.

Это функция, которую я лично использую (перенесена из этого метода расширения C#):

function ConvertTo-ByteArray {

    param([System.Collections.BitArray]$BitArray)

    $numBytes = [System.Math]::Ceiling($BitArray.Count / 8)

    $bytes = New-Object byte[] $numBytes
    $byteIndex = 0 
    $bitIndex = 0

    for ($i = 0; $i -lt $BitArray.Count; $i++) {
        if ($BitArray[$i]){
            $bytes[$byteIndex] = $bytes[$byteIndex] -bor (1 -shl (7 - $bitIndex))
        }
        $bitIndex++
        if ($bitIndex -eq 8) {
            $bitIndex = 0
            $byteIndex++
        }
    }

    ,$bytes
}

Вторая проблема - не само преобразование, а способ добавления отступов к byte строки:

[Convert]::ToString($_, 2).PadRight(8,'0')

PadRight() добавит нули в конец строки, а не в начале.

Измените это на PadLeft() и вы получите правильный вывод:

($result | % { [Convert]::ToString($_, 2).PadLeft(8,'0')})
Другие вопросы по тегам