PowerShell Get-Content vs Import-Csv: Which to Use for Files

PowerShell Get-Content vs Import-Csv: Which to Use for Files

PowerShell Tips Editor 4 min read
PowerShell Get-Content vs Import-Csv: Which to Use for Files

When you reach for powershell get-content vs import-csv to load a data file, choosing the wrong cmdlet costs you twenty lines of manual parsing. Get-Content returns raw strings — one per line — while Import-Csv returns typed objects with named properties matching your header row. If the file is a proper CSV with headers, Import-Csv is nearly always the right tool. Understanding when each excels saves time and keeps your scripts readable.

Quick Answer / TL;DR

Use Import-Csv for any file with comma-separated headers and rows. Use Get-Content for plain text, log files, or any file that is not tabular data.

Get-Content: Line-by-Line Text

Get-Content reads a file and returns each line as a String object. It makes no assumptions about structure — it is equally useful for reading a PowerShell script, a log file, or a config file. Each line is a separate pipeline object, so you can pipe directly into Select-String, ForEach-Object, or any string-processing cmdlet. Use -Raw to get the entire file as one string, which matters for regex patterns that span lines.

# Read every line as a string
$lines = Get-Content -Path C:\Logs\app.log
$lines.Count          # number of lines

# Read entire file as single string
$raw = Get-Content -Path C:\Scripts\config.ini -Raw

Import-Csv: Structured Objects

Import-Csv reads a CSV file and converts each data row into a PSCustomObject. The first row (or a value you supply with -Header) becomes the property names. You immediately get dot-notation access to columns, which means no string splitting, no array indexing, and no guessing about column order. The result integrates seamlessly with Where-Object, Select-Object, and Export-Csv.

# users.csv has columns: Name,Department,Email
$users = Import-Csv -Path C:\Data\users.csv

foreach ($user in $users) {
    Write-Host "$($user.Name) works in $($user.Department)"
}

Accessing CSV Columns vs Parsing Lines

The practical difference becomes obvious when you try to filter. With Import-Csv, filtering by department is one readable line. With Get-Content, you must split on commas, handle quoted fields, and track column positions manually — fragile and verbose.

# Import-Csv: clean and direct
$itUsers = Import-Csv C:\Data\users.csv | Where-Object Department -eq 'IT'

# Get-Content: tedious equivalent
$itUsers = Get-Content C:\Data\users.csv |
    Select-Object -Skip 1 |          # skip header
    ForEach-Object {
        $cols = $_ -split ','
        if ($cols[1] -eq 'IT') { $cols }
    }

Handling Headers and Delimiters

Import-Csv supports custom delimiters with -Delimiter and custom headers with -Header. If your file uses semicolons (common in European locales) or tabs, pass the character explicitly. If there is no header row, supply the names yourself so the first data row is not consumed as headers.

# Semicolon-delimited file
Import-Csv -Path C:\Data\export.csv -Delimiter ';'

# No header row in file — supply names
Import-Csv -Path C:\Data\raw.csv -Header 'Name','Age','City'

When the File Is Not a CSV

Get-Content is the correct choice for log files, INI files, scripts, XML (before parsing), JSON (before parsing), and any binary-adjacent text format. Import-Csv on a non-CSV file creates garbage objects with mangled property names. Conversely, Get-Content on a CSV gives you header-plus-data strings you then must parse yourself — pointless when Import-Csv exists.

Performance on Large Files

Both cmdlets load the file into memory by default. For multi-gigabyte files, consider Get-Content -ReadCount 1000 to stream in chunks, or [System.IO.StreamReader] for maximum throughput. Import-Csv on a 500 MB CSV will consume significant memory as all rows become objects. For large CSVs, filter with Where-Object early or stream with a StreamReader and manual parsing. Get-Content -ReadCount 0 (all at once) is fastest for small files but problematic for large ones.

Common Errors and Fixes

  • Get-Content on CSV gives strings not objects — no column access. When you run Get-Content users.csv and then try $result[0].Name, you get $null because each element is a plain string. Switch to Import-Csv whenever you need column-level access.
  • Import-Csv on a non-CSV file creates garbage objects. If you run Import-Csv app.log, the cmdlet treats the first line as headers and subsequent lines as values, producing nonsense objects. Use Get-Content for non-tabular files and parse manually if structure is needed.

Related Cmdlets / See Also

Wrapping Up

Pick Import-Csv when your file has comma-separated rows with headers — you get instant object access and pipeline compatibility with no parsing code. Reach for Get-Content for everything else: logs, scripts, configs, and any non-tabular text. Matching the cmdlet to the file structure keeps your code short and correct.

Send-Item -To