Question

How to Split a String by Newlines in .NET (C#)

csharp.netstringsplit

Question

I need to split a string into separate lines in .NET. The main string method I know for this is Split, but I am not sure how to use it cleanly with newline characters. What is the best way to split a string by newlines?

For example, I want to handle text like this:

string text = "first line\r\nsecond line\nthird line\rfourth line";

What is the best approach in .NET to turn that into individual lines?

Short Answer

By the end of this page, you will understand how newline characters work in .NET, how to split strings into lines using Split, and how to handle different line ending formats such as \r\n, \n, and \r. You will also learn which approach is safest when text may come from different operating systems.

Concept

In .NET, a newline is not always represented by the same character sequence.

Common line endings are:

  • \r\n — Windows
  • \n — Unix/Linux/macOS (modern)
  • \r — older Mac systems

This matters because text can come from many sources:

  • files
  • APIs
  • copied user input
  • logs
  • CSV or text processing tools

If you split only on one newline format, your code may work for some inputs and fail for others.

In C#, the string.Split() method can split on strings or characters. Since line endings may be one or two characters long, the most reliable beginner-friendly approach is usually to split on all common newline sequences.

A common pattern is:

string[] lines = text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

This tells .NET:

  1. Look for any of these line endings.
  2. Split the text wherever one appears.
  3. Return all parts as an array of strings.

If you want to ignore empty lines, use StringSplitOptions.RemoveEmptyEntries instead.

This concept matters because line-based processing is everywhere in real programming: reading configuration files, parsing logs, importing text data, and handling user-generated content.

Mental Model

Think of a long string as a sheet of paper with multiple written lines.

Newline characters are the invisible line break marks between those lines. Splitting by newlines is like cutting the paper at every line break so that each line becomes its own piece.

The tricky part is that different systems draw the line break mark differently:

  • Windows uses a two-part mark: \r\n
  • Unix uses a one-part mark: \n
  • Older systems may use \r

So instead of looking for only one kind of cut mark, good .NET code usually checks for all common ones.

Take Quiz

Syntax and Examples

The basic syntax is:

string[] lines = text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

Example: keep all lines

string text = "first line\r\nsecond line\nthird line\rfourth line";

string[] lines = text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

foreach (string line in lines)
{
    Console.WriteLine(line);
}

Output:

first line
second line
third line
fourth line

Example: remove empty lines

string text = "first line\n\nsecond line\r\n\r\nthird line";

string[] lines = text.Split(
    new[] { "\r\n", "\n", "\r" },
    StringSplitOptions.RemoveEmptyEntries
);

foreach (string line in lines)
{
    Console.WriteLine(line);
}

Output:

first line
second line
third line

Using Environment.NewLine

If you are sure the text uses the current system's newline format, you can do this:

string[] lines = text.Split(new[] { Environment.NewLine }, StringSplitOptions.None);

However, this is only safe when the input definitely matches the current environment. If text may come from other platforms, split on all common newline types instead.

Step by Step Execution

Consider this code:

string text = "apple\r\nbanana\ncarrot";
string[] lines = text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

Step by step

  1. text contains three words separated by line endings.
  2. The first separator is \r\n, so .Split() finds that between apple and banana.
  3. The second separator is \n, so .Split() finds that between banana and carrot.
  4. The string is cut into pieces at those positions.
  5. The result is an array:
lines[0] = "apple"
lines[1] = "banana"
lines[2] = "carrot"

Trace example with empty lines

string text = "a\n\nb";
string[] lines = text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

Result:

lines[0] = "a"
lines[1] = ""
lines[2] = "b"

That empty string appears because there was a blank line between a and b.

If you use StringSplitOptions.RemoveEmptyEntries, the empty entry is removed.

Real World Use Cases

Splitting text into lines is common in many practical situations.

Reading text files

You may load a text file into memory and process each line:

string content = File.ReadAllText("data.txt");
string[] lines = content.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

Parsing logs

Application logs are often line-based. Splitting lets you inspect entries one by one.

Importing pasted user input

A user might paste one email address or product code per line. Your code can split the input into separate values.

Processing API responses

Some APIs or command-line tools return plain text with newline-separated records.

Building tools for configuration data

Simple config formats often store one value per line, so splitting is the first step before validation or parsing.

Take Quiz

Real Codebase Usage

In real projects, developers usually do more than just call Split().

1. Validation before splitting

Check for null or empty input first:

if (string.IsNullOrEmpty(text))
{
    return Array.Empty<string>();
}

string[] lines = text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

This is a common guard clause.

2. Remove empty lines when blank lines do not matter

string[] lines = text.Split(
    new[] { "\r\n", "\n", "\r" },
    StringSplitOptions.RemoveEmptyEntries
);

Useful when parsing lists of IDs, tags, or commands.

3. Trim each line after splitting

Real input often contains extra spaces:

string[] lines = text
    .Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.RemoveEmptyEntries)
    .Select(line => line.Trim())
    .ToArray();

This pattern is very common in import and validation code.

4. Combine with filtering

string[] validLines = text
    .Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None)
    .Where(line => !string.IsNullOrWhiteSpace(line))
    .ToArray();

This is useful when blank or whitespace-only lines should be ignored.

5. Prefer explicit handling for cross-platform input

In shared systems, text may come from Windows, Linux, browsers, or databases. That is why many codebases avoid relying only on Environment.NewLine.

Common Mistakes

Mistake 1: Splitting only on Environment.NewLine

string[] lines = text.Split(new[] { Environment.NewLine }, StringSplitOptions.None);

Why this can fail:

  • On Windows, Environment.NewLine is usually \r\n
  • But your input may contain only \n
  • Then the string will not split correctly

Use this only when you fully control the input format.

Mistake 2: Splitting on \n only and leaving \r

string[] lines = text.Split('\n');

If your text contains Windows line endings (\r\n), each line may end with an extra \r character.

Example problem:

string text = "one\r\ntwo";
string[] lines = text.Split('\n');

Console.WriteLine(lines[0] == "one"); // false
Console.WriteLine(lines[0]);           // prints "one\r"

Better:

string[] lines = text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

Mistake 3: Forgetting about empty lines

string text = "a\n\nb";
string[] lines = text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

This gives:

"a", "", "b"

If that is not what you want, use:

StringSplitOptions.RemoveEmptyEntries

Mistake 4: Not handling null

string text = null;
string[] lines = text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

This throws a NullReferenceException.

Safer approach:

string[] lines = string.IsNullOrEmpty(text)
    ? Array.Empty<string>()
    : text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

Comparisons

ApproachExampleBest forLimitation
Split on all common newline typestext.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None)Cross-platform text inputSlightly more verbose
Split on Environment.NewLinetext.Split(new[] { Environment.NewLine }, StringSplitOptions.None)Input known to match current OSCan fail for text from another platform
Split on \n onlytext.Split('\n')Quick scripts when input format is knownCan leave \r at end of lines
Read line by line with StringReaderreader.ReadLine()Streaming-style processingMore code if you just need an array

Split vs StringReader

Split is ideal when:

  • you already have the whole string
  • you want an array of lines quickly

StringReader is useful when:

  • you want to process one line at a time
  • you want code that feels similar to file reading

Example with StringReader:

using System.IO;

string text = "one\r\ntwo\nthree";
using var reader = new StringReader(text);

string? line;
while ((line = reader.ReadLine()) != null)
{
    Console.WriteLine(line);
}

This automatically handles common newline formats and is often a clean alternative.

Take Quiz

Cheat Sheet

// Best general-purpose newline split
string[] lines = text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

// Ignore blank lines
string[] linesNoEmpty = text.Split(
    new[] { "\r\n", "\n", "\r" },
    StringSplitOptions.RemoveEmptyEntries
);

// Only when input definitely matches current OS newline
string[] envLines = text.Split(new[] { Environment.NewLine }, StringSplitOptions.None);

Common newline sequences

  • \r\n = Windows
  • \n = Unix/Linux/macOS
  • \r = older Mac format

Rules of thumb

  • Use all common newline separators for cross-platform safety.
  • Use RemoveEmptyEntries if blank lines should be ignored.
  • Check for null before calling Split().
  • Be careful when splitting only on \n, because \r may remain.

Handy safe pattern

string[] lines = string.IsNullOrEmpty(text)
    ? Array.Empty<string>()
    : text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None);

FAQ

How do I split a string by line breaks in C#?

Use Split with all common newline sequences:

text.Split(new[] { "\r\n", "\n", "\r" }, StringSplitOptions.None)

Should I use Environment.NewLine to split lines?

Only if you know the input uses the same newline style as the current system. For cross-platform input, splitting on all common newline formats is safer.

Why does splitting on \n sometimes leave strange characters?

Because Windows lines usually end with \r\n. If you split only on \n, the \r may remain at the end of each line.

How do I ignore blank lines when splitting text?

Use StringSplitOptions.RemoveEmptyEntries.

What is the difference between \r, \n, and \r\n?

They are different line ending formats used by different operating systems and tools.

Is StringReader better than Split?

It depends. Split is simpler when you want all lines at once. StringReader is useful when you want to process lines one by one.

What happens if the string is null?

Calling Split() on null throws a NullReferenceException. Check with string.IsNullOrEmpty() first.

Take Quiz

Mini Project

Description

Build a small C# utility that takes a block of text, splits it into lines safely, removes blank lines, trims extra spaces, and prints the cleaned result. This demonstrates practical newline handling similar to what you would do when processing pasted user input or imported text.

Goal

Create a method that converts multiline text into a clean array of non-empty lines.

Requirements

  • Accept a multiline string as input.
  • Split the text using common newline formats.
  • Remove empty lines.
  • Trim whitespace from each line.
  • Print the cleaned lines with their index numbers.
Take Quiz

Keep learning

Related questions

View more