StringBuilder and Get-Content

This topic contains 3 replies, has 3 voices, and was last updated by Profile photo of Joakim Svendsen Joakim Svendsen 3 years, 4 months ago.

  • Author
  • #11804
    Profile photo of Stephen Yeadon
    Stephen Yeadon

    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.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



    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...

  • #11805
    Profile photo of Dave Wyatt
    Dave Wyatt

    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)
    # Using a loop
    $stringBuilder = New-Object System.Text.StringBuilder
    Get-Content -Path C:\temp\file.txt |
    ForEach-Object {
        $null = $stringBuilder.AppendLine($_)
  • #11806
    Profile photo of Stephen Yeadon
    Stephen Yeadon

    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.

  • #11811
    Profile photo of Joakim Svendsen
    Joakim Svendsen

    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
    PS D:\temp> (New-Object Text.StringBuilder).Append(((gc xml.xml) -join "`n")).ToString()

You must be logged in to reply to this topic.