How to Convert a Byte Array to a String in PowerShell

To convert a byte array to a string in PowerShell, decode it with the matching text encoding, usually UTF-8. [System.Text.Encoding]::UTF8.GetString() takes the bytes and returns the text:

$bytes = [byte[]](72, 101, 108, 108, 111, 44, 32, 65, 117, 115, 116, 105, 110)
[System.Text.Encoding]::UTF8.GetString($bytes)

Output:

Hello, Austin

The reverse is GetBytes(), and those two methods are most of what you need. The rest of this guide covers picking the right encoding, creating byte arrays, and converting bytes to hex, Base64 and files.

I ran each example in PowerShell 7.6 and Windows PowerShell 5.1. Two things only work in one version, and I point those out where they come up.

Convert a string to a byte array

GetBytes() turns text into bytes. Notice that this four-letter word needs five bytes, not four:

$bytes = [System.Text.Encoding]::UTF8.GetBytes('Café')
$bytes -join ' '
"Byte count: $($bytes.Count)"

Output:

67 97 102 195 169
Byte count: 5

The é takes two bytes (195 and 169) in UTF-8, while plain English letters take one each. Joining with -join ' ' prints the bytes on one line instead of one per line.

Why does the encoding matter?

A byte array doesn’t remember which encoding made it. You have to decode with the same encoding you encoded with. Here’s the same word in three encodings:

$text = 'Café'
foreach ($name in 'UTF8', 'Unicode', 'ASCII') {
    $encoding = [System.Text.Encoding]::$name
    $bytes    = $encoding.GetBytes($text)
    $back     = $encoding.GetString($bytes)
    '{0,-8} {1} bytes: {2,-22} back to text: {3}' -f $name, $bytes.Count, ($bytes -join ' '), $back
}

Output:

UTF8     5 bytes: 67 97 102 195 169      back to text: Café
Unicode  8 bytes: 67 0 97 0 102 0 233 0  back to text: Café
ASCII    4 bytes: 67 97 102 63           back to text: Caf?
PowerShell string to byte array with UTF8, Unicode and ASCII encoding
The same text in three encodings in PowerShell 7

UTF-8 and Unicode (UTF-16) both round-trip correctly. ASCII can’t store é, so it silently becomes a question mark and the original is lost.

Decoding with the wrong encoding gives you the garbled text you’ve probably seen on web pages. These are UTF-8 bytes decoded as Windows-1252:

$bytes = [System.Text.Encoding]::UTF8.GetBytes('Café')
[System.Text.Encoding]::GetEncoding('windows-1252').GetString($bytes)

Output:

Café

When you get bytes from a file, an API or a registry value, check which encoding it uses. For most modern data, the answer is UTF-8.

Create a byte array

Cast a list of numbers to [byte[]], or create an empty array of a set size with [byte[]]::new(). Hex values like 0x50 work too:

$header = [byte[]](0x50, 0x4B, 0x03, 0x04)
$buffer = [byte[]]::new(8)

"Header: $($header -join ' ')"
"Buffer: $($buffer -join ' ')"

Output:

Header: 80 75 3 4
Buffer: 0 0 0 0 0 0 0 0

Those four bytes are the signature at the start of a ZIP file, including .docx and .xlsx files, which is a handy way to check a file’s real type. A new array is filled with zeros. Each item must be between 0 and 255:

try {
    [byte]300
}
catch {
    $_.Exception.Message
}

Output:

Cannot convert value "300" to type "System.Byte". Error: "Value was either too large or too small for an unsigned byte."

Watch out when you add bytes

+= on a byte array quietly turns it into a general object array, unless the variable itself is typed:

$data = [byte[]](1, 2)
$data += 3
"Untyped variable: $($data.GetType().Name)"

[byte[]]$typed = 1, 2
$typed += 3
"Typed variable:   $($typed.GetType().Name)"

Output:

Untyped variable: Object[]
Typed variable:   Byte[]

Put [byte[]] in front of the variable name when you declare it, and every later assignment stays a byte array. That matters when you pass it to a .NET method that expects byte[].

Convert a byte array to a hex string

[System.BitConverter]::ToString() gives you hex pairs separated by dashes. Remove the dashes with -replace, or format each byte yourself for lowercase hex:

$bytes = [System.Text.Encoding]::UTF8.GetBytes('Order 42')

[System.BitConverter]::ToString($bytes)
[System.BitConverter]::ToString($bytes) -replace '-'
($bytes | ForEach-Object { $_.ToString('x2') }) -join ''

Output:

4F-72-64-65-72-20-34-32
4F72646572203432
4f72646572203432
PowerShell convert byte array to hex string with BitConverter
Byte array to hex in PowerShell 7

PowerShell 7 has a shorter way. [System.Convert]::ToHexString() and FromHexString() convert in both directions:

$bytes = [System.Text.Encoding]::UTF8.GetBytes('Order 42')
$hex   = [System.Convert]::ToHexString($bytes)

$hex
[System.Text.Encoding]::UTF8.GetString([System.Convert]::FromHexString($hex))

Output in PowerShell 7:

4F72646572203432
Order 42

Those two methods don’t exist in Windows PowerShell 5.1, which throws a “does not contain a method named ‘ToHexString'” error. In 5.1, convert hex back to bytes two characters at a time:

$hex   = '4F72646572203432'
$bytes = [byte[]]$(for ($i = 0; $i -lt $hex.Length; $i += 2) {
    [System.Convert]::ToByte($hex.Substring($i, 2), 16)
})

[System.Text.Encoding]::UTF8.GetString($bytes)

Output:

Order 42

Convert a byte array to Base64 and back

Base64 turns any bytes into plain text that’s safe to paste into JSON, XML or an email. ToBase64String() encodes, and FromBase64String() decodes:

$bytes  = [System.Text.Encoding]::UTF8.GetBytes('Invoice 1042: $1,249.50')
$base64 = [System.Convert]::ToBase64String($bytes)
$base64

$decoded = [System.Convert]::FromBase64String($base64)
[System.Text.Encoding]::UTF8.GetString($decoded)

Output:

SW52b2ljZSAxMDQyOiAkMSwyNDkuNTA=
Invoice 1042: $1,249.50
PowerShell convert byte array to Base64 string and back in Windows PowerShell 5.1
Base64 in Windows PowerShell 5.1

If the text isn’t valid Base64, FromBase64String() throws an error, so wrap it in try/catch when the input comes from outside your script:

try {
    [System.Convert]::FromBase64String('Invoice-1042!')
}
catch {
    $_.Exception.InnerException.Message
}

Output:

The input is not a valid Base-64 string as it contains a non-base 64 character, more than two padding characters, or an illegal character among the padding characters.

For more Base64 examples, see how to convert a string to Base64 in PowerShell and how to convert files to Base64.

Read and write a file as bytes

[System.IO.File]::ReadAllBytes() loads a whole file into a byte array, and WriteAllBytes() saves one. Both work the same in PowerShell 7 and 5.1:

Set-Content -Path C:\psfaqs\hello.txt -Value 'Hi there' -NoNewline

$bytes = [System.IO.File]::ReadAllBytes('C:\psfaqs\hello.txt')
$bytes -join ' '

[System.IO.File]::WriteAllBytes('C:\psfaqs\hello-copy.bin', $bytes)
"Copy size: $((Get-Item -Path C:\psfaqs\hello-copy.bin).Length) bytes"

Output:

72 105 32 116 104 101 114 101
Copy size: 8 bytes

Pass full paths to these .NET methods. A relative path is resolved from the folder PowerShell started in, not your current location.

Get-Content in PowerShell 7 vs 5.1

Get-Content can read bytes too, but the parameter changed. PowerShell 7 uses -AsByteStream:

Get-Content -Path C:\psfaqs\hello.txt -AsByteStream -TotalCount 2

Output in PowerShell 7:

72
105

Windows PowerShell 5.1 uses -Encoding Byte instead:

Get-Content -Path C:\psfaqs\hello.txt -Encoding Byte -TotalCount 2

Output in Windows PowerShell 5.1:

72
105

Each version rejects the other’s syntax, so scripts that must run in both should use ReadAllBytes(). The Encoding.GetString documentation lists the other decoding options.

Frequently Asked Questions

How do I convert a byte array to a string in PowerShell?

Use [System.Text.Encoding]::UTF8.GetString($bytes). Swap UTF8 for Unicode or ASCII if the bytes were created with that encoding.

How do I convert a string to a byte array in PowerShell?

Use [System.Text.Encoding]::UTF8.GetBytes('text'). It returns a byte[] with one or more bytes per character.

Why does my converted string show strange characters?

The bytes were decoded with a different encoding than the one that created them. Decode UTF-8 bytes with UTF-8, UTF-16 bytes with Unicode, and so on.

How do I convert a byte array to hex in PowerShell?

Use [System.BitConverter]::ToString($bytes) -replace '-'. In PowerShell 7, [System.Convert]::ToHexString($bytes) does it in one call.

How do I convert a Base64 string to a byte array?

Use [System.Convert]::FromBase64String($text). It throws an error if the text isn’t valid Base64.

For more on arrays in general, try these: