CRLF
C#
.NET
line endings
coding tips

What is a quick way to force CRLF in C / .NET?

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Line endings look trivial until they break tests, parsers, or cross-platform workflows. Windows tooling often expects CRLF (\r\n), while Unix-style environments use LF (\n). In .NET code that generates files, logs, or protocol payloads, inconsistent endings can cause noisy diffs, unexpected parser behavior, or failing snapshots in CI.

A quick fix is replacing \n with \r\n, but doing this blindly can produce double carriage returns (\r\r\n) when input already contains mixed endings. The reliable strategy is normalization: first collapse all newline variants to LF, then expand to CRLF. This article covers safe patterns for strings, stream writing, and repository-level consistency so your output is predictable.

Core Sections

Use explicit CRLF where protocol requires it

If a format explicitly requires CRLF (for example, some legacy protocols), write it directly.

csharp
1var request =
2    "HEADER: value\r\n" +
3    "Another: value\r\n" +
4    "\r\n" +
5    "body";

For protocol text, avoid Environment.NewLine because behavior changes by OS. Protocol requirements should be invariant.

Normalize arbitrary text safely

When input may contain mixed endings, normalize in two steps.

csharp
1public static string ForceCrlf(string input)
2{
3    if (input is null) return string.Empty;
4
5    // Step 1: collapse CRLF and CR to LF
6    var normalizedLf = input.Replace("\r\n", "\n").Replace("\r", "\n");
7
8    // Step 2: expand LF to CRLF
9    return normalizedLf.Replace("\n", "\r\n");
10}

This avoids accidental \r\r\n output and works with text copied from multiple platforms.

Configure StreamWriter for predictable file output

StreamWriter.WriteLine uses TextWriter.NewLine. Set it explicitly when writing files.

csharp
1using var writer = new StreamWriter("output.txt", append: false, encoding: new UTF8Encoding(false));
2writer.NewLine = "\r\n";
3
4writer.WriteLine("first");
5writer.WriteLine("second");

This is cleaner than manual concatenation in loops and keeps code readable.

Handle existing files without corrupting content

When converting full files, preserve encoding and avoid binary files.

csharp
1var path = "notes.txt";
2var text = File.ReadAllText(path);
3var converted = ForceCrlf(text);
4File.WriteAllText(path, converted, new UTF8Encoding(false));

For repositories with many files, prefer tooling (.gitattributes, editor settings) over ad-hoc conversions in application logic.

Use .gitattributes for team-wide consistency

Source control should enforce newline policy so developers do not fight platform-specific diffs.

gitattributes
1* text=auto
2*.sln text eol=crlf
3*.cs text eol=crlf
4*.sh text eol=lf

This keeps project standards consistent regardless of each developer’s operating system.

Testing line endings

When line endings matter, assert exact bytes or escaped sequences.

csharp
1[Fact]
2public void ForceCrlf_ConvertsMixedEndings()
3{
4    var input = "a\n b\r\n c\r";
5    var output = ForceCrlf(input);
6    Assert.DoesNotContain("\r\r\n", output);
7    Assert.DoesNotContain("\n", output.Replace("\r\n", ""));
8}

Targeted tests prevent regressions when utility code is reused across services.

Common Pitfalls

  • Replacing \n with \r\n directly on unknown input, which can create double carriage returns.
  • Using Environment.NewLine for protocol formats that require a fixed newline convention.
  • Converting every file indiscriminately, including binaries, and corrupting content.
  • Relying only on local editor settings instead of enforcing repository-wide rules with .gitattributes.
  • Forgetting newline-sensitive tests, allowing subtle cross-platform issues to reappear later.

Summary

Forcing CRLF in .NET is straightforward when you normalize input first, then emit a consistent target newline. Use explicit "\r\n" for protocol strings, configure StreamWriter.NewLine for file generation, and apply .gitattributes to keep team workflows stable across platforms. Most issues come from partial conversion strategies or unclear ownership of newline policy. With a small utility and a repository standard, line-ending behavior becomes deterministic and maintenance-friendly.

For larger systems, put newline normalization behind a shared helper and require it in code paths that generate text artifacts. That keeps behavior uniform across services and prevents one-off implementations from reintroducing mixed endings. Combined with CI tests, this gives you long-term protection against platform-related newline drift. If line endings are part of an external contract, include fixture-based integration tests that assert raw bytes, not just rendered strings.


Related reading
Course
Intermediate
27 lessons
14 hours
OOD Fundamentals

Master object-oriented design from first principles, SOLID, design patterns, and classic interview problems with hands-on coding.

View the course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.