To create a file with content in PowerShell, use Set-Content -Path file -Value 'text'. It creates the file, or replaces its content if the file already exists:
Set-Content -Path C:\psfaqs\Files\welcome.txt -Value 'Welcome to the Austin office!'
Get-Content -Path C:\psfaqs\Files\welcome.txt
Output:
Welcome to the Austin office!
Below I cover multiline text, encoding, and JSON and XML files. I ran every example in PowerShell 7.6 and Windows PowerShell 5.1 and show where they write different files.
Write several lines
A here-string keeps the line breaks you type. Start it with @’ on its own line and end it with ‘@ at the start of a line:
$body = @'
Server=SQL01
Database=Orders
Port=1433
'@
Set-Content -Path C:\psfaqs\Files\app.config -Value $body
"Lines written: $((Get-Content -Path C:\psfaqs\Files\app.config).Count)"
Output:
Lines written: 3
Use @” “@ instead if you want variables inside to expand. Adding new lines to strings covers `n and here-strings in more detail.
Write an array, then append
Pass an array to Set-Content and each item becomes a line. Add-Content appends more lines later:
$cities = 'Austin', 'Denver', 'Miami'
Set-Content -Path C:\psfaqs\Files\cities.txt -Value $cities
Add-Content -Path C:\psfaqs\Files\cities.txt -Value 'Seattle'
Get-Content -Path C:\psfaqs\Files\cities.txt
Output:
Austin
Denver
Miami
Seattle
Add-Content explains appending, including the missing-newline trap.
Set-Content vs Out-File: the encoding matters
In Windows PowerShell 5.1, Set-Content and Out-File write different encodings. This writes the word Café three ways and checks the bytes:
Set-Content -Path C:\psfaqs\Files\set-content.txt -Value 'Café'
'Café' | Out-File -FilePath C:\psfaqs\Files\out-file.txt
Set-Content -Path C:\psfaqs\Files\utf8.txt -Value 'Café' -Encoding utf8
foreach ($name in 'set-content', 'out-file', 'utf8') {
$bytes = [IO.File]::ReadAllBytes("C:\psfaqs\Files\$name.txt")
'{0,-12} {1,2} bytes, starts with {2}' -f $name, $bytes.Length, (($bytes[0..1] | ForEach-Object { '{0:X2}' -f $_ }) -join ' ')
}
Output in PowerShell 7:
set-content 7 bytes, starts with 43 61
out-file 7 bytes, starts with 43 61
utf8 7 bytes, starts with 43 61
Output in Windows PowerShell 5.1:
set-content 6 bytes, starts with 43 61
out-file 14 bytes, starts with FF FE
utf8 10 bytes, starts with EF BB

PowerShell 7 writes UTF-8 without a byte order mark everywhere. In 5.1, Set-Content writes ANSI, Out-File writes UTF-16 (FF FE), and -Encoding utf8 adds a BOM (EF BB BF). Microsoft explains the defaults in about_Character_Encoding.
Out-File cuts wide tables
Out-File writes objects the way the console would show them, so long values get cut at the console width. Add -Width:
$item = [pscustomobject]@{ Name = 'Contoso'; Notes = ('x' * 150); City = 'Austin' }
$item | Format-Table | Out-File -FilePath C:\psfaqs\Files\table.txt
"Default width keeps all notes: $((Get-Content -Path C:\psfaqs\Files\table.txt -Raw).Contains('x' * 150))"
$item | Format-Table | Out-File -FilePath C:\psfaqs\Files\table.txt -Width 300
"With -Width 300 keeps all notes: $((Get-Content -Path C:\psfaqs\Files\table.txt -Raw).Contains('x' * 150))"
Output:
Default width keeps all notes: False
With -Width 300 keeps all notes: True
For data you’ll read back, export CSV or JSON instead of formatted tables.
Create a JSON file
Build an ordered hashtable, convert it with ConvertTo-Json and save it. ConvertFrom-Json reads it back as objects:
$settings = [ordered]@{
AppName = 'OrderSync'
Region = 'US-East'
Servers = 'WEB01', 'WEB02'
Database = [ordered]@{ Server = 'SQL01'; Port = 1433 }
}
$settings | ConvertTo-Json | Set-Content -Path C:\psfaqs\Files\settings.json
$back = Get-Content -Path C:\psfaqs\Files\settings.json -Raw | ConvertFrom-Json
"Read back: $($back.AppName) uses $($back.Database.Server) on port $($back.Database.Port)"
Output:
Read back: OrderSync uses SQL01 on port 1433
[ordered] keeps the keys in the order you typed them, which makes config files easier to read. ConvertTo-Json has more options.
Nested JSON gets cut at depth 2
ConvertTo-Json only goes two levels deep by default. PowerShell 7 warns you, while Windows PowerShell 5.1 silently writes a type name instead of your data:
$config = [ordered]@{ App = 'Orders'; Env = [ordered]@{ Prod = [ordered]@{ Db = [ordered]@{ Server = 'SQL01' } } } }
'Default depth:'
$config | ConvertTo-Json -Compress
'-Depth 5:'
$config | ConvertTo-Json -Compress -Depth 5
Output in PowerShell 7:
Default depth:
WARNING: Resulting JSON is truncated as serialization has exceeded the set depth of 2.
{"App":"Orders","Env":{"Prod":{"Db":"System.Collections.Specialized.OrderedDictionary"}}}
-Depth 5:
{"App":"Orders","Env":{"Prod":{"Db":{"Server":"SQL01"}}}}

5.1 prints the same truncated JSON without the warning. Add -Depth whenever your data is nested, as the ConvertTo-Json documentation explains.
Create an XML file
For a fixed layout, cast a here-string to [xml], change what you need and save it. Pass Save() a full path:
[xml]$doc = @'
<settings>
<app name="OrderSync" region="US-East" />
<database server="SQL01" port="1433" />
</settings>
'@
$doc.settings.database.port = '14330'
$doc.Save('C:\psfaqs\Files\settings.xml')
[xml]$saved = Get-Content -Path C:\psfaqs\Files\settings.xml -Raw
"Saved port: $($saved.settings.database.port)"
Output:
Saved port: 14330
Save() is a .NET method, so a relative path would land in the folder PowerShell started in, not your current location. New-Item explains that difference.
Build XML from data
When the elements come from a list, create them with XmlDocument:
$doc = New-Object -TypeName System.Xml.XmlDocument
$root = $doc.AppendChild($doc.CreateElement('servers'))
foreach ($name in 'WEB01', 'WEB02') {
$node = $doc.CreateElement('server')
$node.SetAttribute('name', $name)
$node.SetAttribute('city', 'Dallas')
[void]$root.AppendChild($node)
}
$doc.Save('C:\psfaqs\Files\servers.xml')
Get-Content -Path C:\psfaqs\Files\servers.xml
Output:
<servers>
<server name="WEB01" city="Dallas" />
<server name="WEB02" city="Dallas" />
</servers>

Microsoft’s XmlDocument reference lists methods like CreateAttribute and SelectNodes. The Set-Content documentation covers -NoNewline and -Encoding.
Frequently Asked Questions
How do I create a file with content in PowerShell?
Use Set-Content -Path C:\Temp\notes.txt -Value 'text'. It creates the file or replaces its content.
What’s the difference between Set-Content and Out-File?
In Windows PowerShell 5.1, Set-Content writes ANSI and Out-File writes UTF-16. Out-File also formats objects like the console. In PowerShell 7 both write UTF-8.
How do I create a JSON file in PowerShell?
Run $data | ConvertTo-Json -Depth 5 | Set-Content settings.json. Add -Depth for nested data.
How do I create an XML file in PowerShell?
Cast a here-string to [xml] or build an XmlDocument, then call $doc.Save('C:\full\path.xml').
How do I write multiple lines to a file?
Use a here-string or an array: Set-Content -Path file.txt -Value 'line 1', 'line 2'.
Related guides for working with files:
- Create files and folders with New-Item
- Append to a file with Add-Content
- Convert objects to JSON
- Find and replace text in a file
Bijay Kumar is an esteemed author and the mind behind PowerShellFAQs.com, where he shares his extensive knowledge and expertise in PowerShell, with a particular focus on SharePoint projects. Recognized for his contributions to the tech community, Bijay has been honored with the prestigious Microsoft MVP award. With over 15 years of experience in the software industry, he has a rich professional background, having worked with industry giants such as HP and TCS. His insights and guidance have made him a respected figure in the world of software development and administration. Read more.