Skip to content

PowerShell Reading From Files

How to read text, CSV, and JSON files in PowerShell using Get-Content, Import-Csv, and ConvertFrom-Json with line-by-line streaming, raw text handling, and structured data parsing.

Reading data from files is essential for parsing log events, processing external data exports, and importing configuration settings. In PowerShell, reading files goes beyond retrieving raw text characters; cmdlets can stream text line by line, load entire files into memory as single strings, or automatically convert structured formats like CSV and JSON into strongly typed .NET objects.

Reading Text with Get-Content

The Get-Content cmdlet (aliases: gc, cat, type) is the primary cmdlet for reading file contents. By default, it reads text files line by line, emitting each line as an individual System.String object. When captured into a variable, PowerShell collects these strings into a zero-indexed array (System.Object[]).

Consolepowershell
Get-Content -Path "C:\Logs\app.log"
Outputplaintext
2024-03-14 08:30:15 - Service started
2024-03-14 08:31:02 - Connection established
2024-03-14 08:32:47 - Request processed
Consolepowershell
(Get-Content -Path "C:\Logs\app.log").Count
Outputplaintext
3

Where:

  • Each line of the file becomes a separate element in the returned array, allowing you to index or loop through them individually.
  • $LogLines[0] retrieves the first line, $LogLines.Count returns the total number of lines.
Consolepowershell
$LogPath = "C:\Logs\service.log"

if (Test-Path $LogPath) {
    $LogLines = Get-Content -Path $LogPath

    Write-Output "Total lines read: $($LogLines.Count)"

    if ($LogLines.Count -gt 0) {
        Write-Output "First line: $($LogLines[0])"
    }
    else {
        Write-Output "The file is empty."
    }
}
else {
    Write-Output "Log file not found: $LogPath"
}
Outputplaintext
Total lines read: 450
First line: 2024-10-24 08:00:01 [INFO] Service startup initiated.

Reading Entire Files as a Single String (-Raw)

The -Raw switch bypasses line-by-line array splitting. It loads the entire file contents into memory as a single, multi-line string (System.String), preserving all newline characters (\r\n or \n).

Consolepowershell
$content = Get-Content -Path "C:\Logs\app.log" -Raw
$content.GetType().Name
Outputplaintext
String

Using -Raw is significantly faster than standard Get-Content on medium-to-large files and is required when:

  • Passing content to cmdlets that expect a single string, such as ConvertFrom-Json.
  • Performing a find-and-replace across the entire document with -replace.
  • Matching regular expression patterns that span multiple lines.

Reading the First N Lines (-TotalCount / -Head)

The -TotalCount parameter (aliased as -Head) limits the number of lines read from the beginning of the file. This is useful for previewing large files without loading them entirely into memory.

Consolepowershell
Get-Content -Path "C:\Logs\app.log" -TotalCount 2
Outputplaintext
2024-03-14 08:30:15 - Service started
2024-03-14 08:31:02 - Connection established

Where -TotalCount 2 reads only the first two lines, regardless of the file's total size.

Reading the Last N Lines (-Tail)

The -Tail parameter reads lines from the end of the file, functioning similarly to the Unix tail command in PowerShell. It is commonly used to check the most recent entries in a growing log file.

Consolepowershell
Get-Content -Path "C:\Logs\service.log" -Tail 2
Outputplaintext
2024-10-24 08:15:30 [WARN] High memory consumption detected.
2024-10-24 08:15:32 [INFO] Heartbeat acknowledged.

Watching a File in Real Time

Combining -Tail with -Wait streams new lines as they are appended to the file, similar to tail -f in Bash.

Consolepowershell
Get-Content -Path "C:\Logs\app.log" -Tail 5 -Wait

Where:

  • -Wait keeps the command running, printing new lines to the console as they are written to the file.
  • Press Ctrl+C to stop watching.

Reading CSV Files with Import-Csv

Comma-Separated Values (CSV) files are commonly used for exporting system reports and spreadsheets. The Import-Csv cmdlet parses a CSV file directly into an array of [PSCustomObject] instances, taking the first row as property names. This approach is far more useful than treating CSV data as plain text lines.

Given a CSV file servers.csv:

servers.csvcsv
ServerName,IPAddress,Role
web-prod-01,192.168.1.10,WebServer
sql-prod-01,192.168.1.20,Database
app-prod-01,192.168.1.30,Application

Import and interact with the data directly using property dot notation:

read-csv-demo.ps1powershell
$ServerList = Import-Csv -Path "$PSScriptRoot\servers.csv"

foreach ($server in $ServerList) {
    Write-Output "Node: $($server.ServerName) | IP: $($server.IPAddress) | Role: $($server.Role)"
}
Consolepowershell
./read-csv-demo.ps1
Outputplaintext
Node: web-prod-01 | IP: 192.168.1.10 | Role: WebServer
Node: sql-prod-01 | IP: 192.168.1.20 | Role: Database
Node: app-prod-01 | IP: 192.168.1.30 | Role: Application

Where:

  • Each row becomes a distinct object, with column headers automatically mapped to property names.
  • $server.ServerName resolves the value directly without manual string splitting.
  • The result works seamlessly with Where-Object, Select-Object, and other pipeline cmdlets.

Specifying a Custom Delimiter

Consolepowershell
Import-Csv -Path "C:\Data\employees.txt" -Delimiter ";"

Where:

  • -Delimiter ";" parses files that use semicolons instead of the default comma.
  • For tab-separated files, use -Delimiter "`t".

Reading JSON Files

JSON is the standard data interchange format for modern APIs, cloud configuration templates, and settings files. PowerShell does not include a dedicated Import-Json cmdlet. Instead, JSON files are read as raw text using Get-Content -Raw before being parsed with ConvertFrom-Json.

Given a JSON file config.json:

config.jsonjson
{
  "ClusterName": "West-Production",
  "Port": 8443,
  "Enabled": true,
  "Nodes": ["node-01", "node-02"]
}

Read and parse the JSON payload:

read-json-demo.ps1powershell
$Config = Get-Content -Path "$PSScriptRoot\config.json" -Raw | ConvertFrom-Json

[PSCustomObject]@{
    TargetCluster = $Config.ClusterName
    ListenPort    = $Config.Port
    IsActive      = $Config.Enabled
    FirstNode     = $Config.Nodes[0]
    TotalNodes    = $Config.Nodes.Count
}
Consolepowershell
./read-json-demo.ps1
Outputplaintext
TargetCluster : West-Production
ListenPort    : 8443
IsActive      : True
FirstNode     : node-01
TotalNodes    : 2

Where:

  • Get-Content -Raw reads the JSON file as a single uninterrupted text string.
  • ConvertFrom-Json parses the JSON string and converts it into a [PSCustomObject] with matching property types (string, int, bool, array).
  • $Config.Nodes[0] accesses elements in the nested JSON array using standard indexing.

Working with Nested JSON

settings.jsonjson
{
  "app": {
    "name": "InventoryManager",
    "version": "2.1.0"
  },
  "features": ["reporting", "export", "sync"]
}
Consolepowershell
$settings = Get-Content -Path "C:\Config\settings.json" -Raw | ConvertFrom-Json
$settings.app.name
$settings.features[1]
Outputplaintext
InventoryManager
export

Where:

  • Nested JSON objects become nested PSCustomObject properties, accessible via chained dot notation ($settings.app.name).
  • JSON arrays become standard PowerShell arrays, supporting normal indexing.

Practical Example: Multi-Source Server Ingestion Engine

The following script reads a combination of data sources: it parses a JSON configuration file for environmental settings, uses Import-Csv to read target servers, and checks an existing log file with -Tail for prior errors.

ingest-server-configs.ps1powershell
param (
    [string]$ConfigPath = "$PSScriptRoot\config.json",
    [string]$CsvPath    = "$PSScriptRoot\servers.csv",
    [string]$LogPath    = "$PSScriptRoot\deployment.log"
)

$FilesToVerify = @($ConfigPath, $CsvPath)
foreach ($file in $FilesToVerify) {
    if (-not (Test-Path -Path $file -PathType Leaf)) {
        Write-Error "Required input file '$file' is missing."
        exit 1
    }
}

Write-Output "Loading environment parameters from JSON..."
$AppSettings = Get-Content -Path $ConfigPath -Raw | ConvertFrom-Json

Write-Output "Importing server endpoints from CSV..."
$Servers = Import-Csv -Path $CsvPath

$RecentErrors = 0
if (Test-Path -Path $LogPath -PathType Leaf) {
    Write-Output "Auditing last 50 log lines for previous failures..."
    $RecentErrors = (Get-Content -Path $LogPath -Tail 50 | Select-String -Pattern "ERROR|FAIL").Count
}

[PSCustomObject]@{
    ClusterTarget      = $AppSettings.ClusterName
    TargetPort         = $AppSettings.Port
    TotalNodesToDeploy = ($Servers.Count)
    RecentLoggedErrors = $RecentErrors
    ReadyForDeployment = ($RecentErrors -eq 0)
}

Where:

  • Test-Path validates that the required input files exist before reading begins.
  • Get-Content -Raw | ConvertFrom-Json parses environment settings from JSON.
  • Import-Csv converts server rows into structured objects.
  • Get-Content -Tail 50 | Select-String scans only the end of the log file for failure keywords.
  • [PSCustomObject] compiles the results into a consolidated summary.

Execute the script from the console:

Consolepowershell
pwsh ./ingest-server-configs.ps1
Outputplaintext
Loading environment parameters from JSON...
Importing server endpoints from CSV...
Auditing last 50 log lines for previous failures...

ClusterTarget      TargetPort TotalNodesToDeploy RecentLoggedErrors ReadyForDeployment
-------------      ---------- ------------------ ------------------ ------------------
West-Production          8443                  3                  0               True
Navigation