StringBuilder and Get-Content

I have a question. Why would using StringBuilder to append Get-Content produce a System.Object when $StringBuilder.ToString() is called. See below.

$stringBuilder = New-Object System.Text.StringBuilder $content = Get-Content -Path C:\temp\file.txt $stringBuilder.Append($content) $stringBuilder.ToString() # System.Object[]

If I force the $Content to be a string, $stringBuilder.ToString() will return the content of the file but all formatting is lost.

[string]$content = Get-Content -Path C:\temp\file.txt or $stringBuilder.Append([string]$content)

My question is why and how could I fix this? The code is used in a ForEach-Object loop to append files to a file in a particular order. I may be comming at this from a more c# point of view.

Thank in advance…

By default, Get-Content outputs one line at a time. When you pass it directly to a method (or assign it to a variable), you get an array. You have a couple of options, here: you can use Get-Content’s -Raw switch (available in PowerShell 3.0 or later) to make it return the entire file as a single String, or you can use a ForEach-Object loop to append each line to the StringBuilder, one at a time.

I’m not sure what you’re using the StringBuilder for here; just calling ToString() on it doesn’t gain you anything over simply assigning the output from Get-Content -Raw straight to a String variable. Also, keep in mind that StringBuilder’s methods mostly return a reference to the StringBuilder itself, so they can be chained together (ie, $stringBuilder.Append(‘Something’).Append(‘Something Else’) ), so you may want to suppress that output in your script by assigning it to a variable, casting it to void or piping to Out-Null (whatever your preference.)

# Using -Raw
$stringBuilder = New-Object System.Text.StringBuilder

$content = Get-Content -Path C:\temp\file.txt -Raw
$null = $stringBuilder.Append($content)
$stringBuilder.ToString()

# Using a loop
$stringBuilder = New-Object System.Text.StringBuilder

Get-Content -Path C:\temp\file.txt |
ForEach-Object {
    $null = $stringBuilder.AppendLine($_)
}

$stringBuilder.ToString()

Thank you -Raw did the trick. I hadn’t tried that as I thought the problem lay with the string builder object, i didn’t realize that get-content worked that way.

Just for the sake of enlightenment: You could also have used the -join operator and joined the Get-Content-produced array of strings (Get-Content actually adds lots of other metadata, so they’re not technically just strings) with newlines, as demonstrated below. It preserves the formatting of my dummy XML file. Otherwise Dave got it all covered, I think. I’m not sure what you need StringBuilder for(?). The -Raw parameter to Get-Content was added in PowerShell version 3, so you’d need something like this for earlier versions of PowerShell.

PS D:\temp> gc .\xml.xml
<xml>
  <nodes>
    <node>foo</node>
    <node>bar</node>
  </nodes>
<xml>
PS D:\temp> (New-Object Text.StringBuilder).Append(((gc xml.xml) -join "`n")).ToString()
<xml>
  <nodes>
    <node>foo</node>
    <node>bar</node>
  </nodes>
<xml>