C#の改行コードを完全理解|\r\n・\nの違いと文字列置換・環境別の扱い方
はじめに
C#で文字列やテキストファイルを扱っていると、「改行コード」が原因で思った通りに表示されない、置換できない、ファイルの内容が崩れるといった問題に出会うことがあります。
特に、Windowsでよく使われる\r\n、LinuxやmacOSで使われることが多い\n、古い環境で見かける\rの違いを理解していないと、文字列処理やファイル入出力で予期しない不具合が起こります。
C#では、文字列に直接\nや\r\nを書く方法のほか、Environment.NewLine、Console.WriteLine、StringBuilder.AppendLineなど、改行を扱うための方法が複数用意されています。
この記事では、C#の改行コードについて、基本的な意味から、\r\n・\n・\rの違い、文字列への改行の入れ方、Environment.NewLineの使い方、改行コードの置換・削除方法まで詳しく解説します。
1. C#の改行コードとは?まず押さえる基本
1-1. 改行コードとは何か
改行コードとは、テキストの中で「ここで行を変える」という意味を持つ特殊な文字のことです。
画面上では目に見えませんが、文字列やテキストファイルの内部には、改行を表すためのコードが含まれています。
たとえば、次のような文字列があるとします。
C#string text = "1行目\n2行目";
この文字列を表示すると、\nの位置で行が分かれます。
1行目
2行目
つまり、改行コードは普通の文字と同じように文字列の一部として扱われますが、表示上は「改行」として解釈される特殊な文字です。
1-2. C#で使う主な改行表現
C#でよく使われる改行表現には、主に次のようなものがあります。
C#"\n"
"\r\n"
"\r"
Environment.NewLine
それぞれの意味は次の通りです。
\n LF。主にLinux・macOSで使われる改行コード
\r\n CRLF。主にWindowsで使われる改行コード
\r CR。古いMac OSなどで使われていた改行コード
Environment.NewLine 実行環境に応じた改行文字列
C#のソースコード内で改行を表したい場合は、単純に\nを書くこともできますし、Windows形式に合わせて\r\nを書くこともできます。
また、実行環境に合わせた改行コードを使いたい場合は、Environment.NewLineを使います。
1-3. \r・\n・\r\nの意味
\rと\nは、それぞれ異なる意味を持つ制御文字です。
\rはキャリッジリターン、\nはラインフィードを表します。
\r Carriage Return。カーソルを行の先頭に戻す
\n Line Feed。カーソルを次の行に送る
\r\n Carriage Return + Line Feed。行頭に戻して次の行へ進む
現在の一般的な開発では、Windowsでは\r\n、LinuxやmacOSでは\nがよく使われます。
C#の文字列処理では、これらはすべて文字として扱われるため、検索や置換の対象にできます。
C#string windowsText = "1行目\r\n2行目";
string unixText = "1行目\n2行目";
string oldMacText = "1行目\r2行目";
見た目はどれも複数行に表示されることがありますが、内部的な改行コードは異なります。
1-4. 改行コードとエスケープシーケンスの関係
C#で使う\nや\rは、エスケープシーケンスと呼ばれる表記です。
エスケープシーケンスとは、通常の文字として直接書きにくい文字を、バックスラッシュを使って表現する仕組みです。
たとえば、次のようなものがあります。
C#"\n" // 改行
"\r" // キャリッジリターン
"\t" // タブ
"\"" // ダブルクォーテーション
"\\" // バックスラッシュ
C#では、通常の文字列リテラル内で\nと書くと、バックスラッシュとnの2文字ではなく、改行を表す1つの制御文字として解釈されます。
C#string text = "Hello\nWorld";
Console.WriteLine(text);
出力結果は次のようになります。
Hello
World
一方で、バックスラッシュそのものを文字として扱いたい場合は、\\のように書きます。
2. \r\n・\n・\rの違いを正しく理解する
2-1. \r\nはWindowsで使われる改行コード
\r\nは、CRLFと呼ばれる改行コードです。
Windowsのテキストファイルでは、一般的にこの\r\nが改行として使われます。
C#string text = "1行目\r\n2行目\r\n3行目";
Console.WriteLine(text);
出力結果は次の通りです。
1行目
2行目
3行目
Windows環境でメモ帳などを使って作成したテキストファイルでは、各行の末尾に\r\nが入っていることが多いです。
そのため、Windows向けのテキストファイルをC#で生成する場合は、\r\nやEnvironment.NewLineがよく使われます。
ただし、.NETをLinuxやmacOS上で実行している場合、Environment.NewLineは\nになります。Windows形式の改行が必要な場合は、環境依存のEnvironment.NewLineではなく、明示的に\r\nを指定する必要があります。
2-2. \nはLinux・macOSで使われる改行コード
\nは、LFと呼ばれる改行コードです。
Linuxや現在のmacOSでは、一般的に\nが改行コードとして使われます。
C#string text = "1行目\n2行目\n3行目";
Console.WriteLine(text);
出力結果は次の通りです。
1行目
2行目
3行目
Webアプリケーション、API、ログ、CSV、JSONなどでは、環境や仕様によって\nが使われることも多くあります。
また、C#の文字列内で単に改行を表現したいだけであれば、\nでも問題なく表示されるケースが多いです。
ただし、Windows形式のテキストファイルとして出力したい場合や、外部システムが\r\nを要求している場合は、\nだけでは不十分なことがあります。
2-3. \rが使われるケース
\rは、CRと呼ばれる改行コードです。
古いMac OSでは、改行コードとして\rが使われていました。
現在の一般的な環境では、単独の\rを改行コードとして使う場面は少なくなっています。
ただし、まったく使われないわけではありません。
たとえば、コンソール上で同じ行を上書き表示したい場合に、\rを使うことがあります。
C#for (int i = 0; i <= 100; i++)
{
Console.Write($"\r進捗: {i}%");
Thread.Sleep(10);
}
この例では、\rによってカーソルを行頭に戻し、同じ行に進捗を上書き表示しています。
ファイルの改行コードとしてはあまり使いませんが、制御文字としての役割を理解しておくと、コンソール表示などで役立つことがあります。
2-4. 改行コードの違いで起きる不具合
改行コードの違いを意識していないと、C#の文字列処理でさまざまな不具合が発生します。
よくあるのは、Replaceで改行を置換できないケースです。
C#string text = "1行目\r\n2行目";
string result = text.Replace("\n", "");
このコードでは\nだけを削除しているため、文字列内に\rが残る可能性があります。
結果として、見えない制御文字が残り、表示や比較で問題になることがあります。
また、次のような問題も起こります。
文字列比較で一致しない
CSVやTSVの行分割がうまくいかない
ログファイルの表示が崩れる
Gitの差分で不要な変更が大量に出る
外部APIに送信するデータ形式が合わない
たとえば、Windowsで作られたテキストをLinux環境で処理する場合、改行コードが\r\nのままだと、行末に\rが残ってしまうことがあります。
C#string[] lines = text.Split('\n');
foreach (string line in lines)
{
Console.WriteLine($"[{line}]");
}
元の文字列が"A\r\nB\r\nC"の場合、Split('\n')で分割すると、各行の末尾に\rが残る場合があります。
このような不具合を避けるには、改行コードを正規化してから処理するのが有効です。
3. C#で文字列に改行を入れる方法
3-1. 文字列リテラルに\nや\r\nを書く方法
C#で文字列に改行を入れる最も基本的な方法は、文字列リテラルに\nや\r\nを書くことです。
C#string text = "1行目\n2行目";
Console.WriteLine(text);
出力結果は次の通りです。
1行目
2行目
Windows形式の改行コードを明示したい場合は、\r\nを使います。
C#string text = "1行目\r\n2行目";
Console.WriteLine(text);
この方法はシンプルで分かりやすいですが、改行コードが固定されます。
つまり、\nと書けば常にLF、\r\nと書けば常にCRLFになります。
そのため、実行環境に合わせて改行コードを変えたい場合には、Environment.NewLineを使う方が適しています。
3-2. Environment.NewLineを使う方法
Environment.NewLineを使うと、実行環境に応じた改行文字列を取得できます。
C#string text = "1行目" + Environment.NewLine + "2行目";
Console.WriteLine(text);
Windowsで実行した場合、Environment.NewLineは通常\r\nになります。
LinuxやmacOSで実行した場合は、通常\nになります。
文字列補間と組み合わせることもできます。
C#string name = "山田";
string message = $"こんにちは、{name}さん{Environment.NewLine}今日もよろしくお願いします。";
Console.WriteLine(message);
出力結果は次のようになります。
こんにちは、山田さん
今日もよろしくお願いします。
OSに合わせた自然な改行コードを使いたい場合は、Environment.NewLineが便利です。
3-3. Console.WriteLineで改行する方法
コンソールに文字列を出力する場合は、Console.WriteLineを使うことで、出力後に自動的に改行されます。
C#Console.WriteLine("1行目");
Console.WriteLine("2行目");
Console.WriteLine("3行目");
出力結果は次の通りです。
1行目
2行目
3行目
Console.Writeは改行しません。
C#Console.Write("1行目");
Console.Write("2行目");
出力結果は次のようになります。
1行目2行目
一方、Console.WriteLineは文字列の末尾に改行を追加します。
C#Console.WriteLine("1行目");
Console.WriteLine("2行目");
コンソールアプリでは、明示的に\nを書くよりも、行単位で出力したい場合はConsole.WriteLineを使う方が自然です。
3-4. StringBuilder.AppendLineで改行する方法
複数行の文字列を効率よく組み立てる場合は、StringBuilderのAppendLineが便利です。
C#using System.Text;
StringBuilder sb = new StringBuilder();
sb.AppendLine("1行目");
sb.AppendLine("2行目");
sb.AppendLine("3行目");
string text = sb.ToString();
Console.WriteLine(text);
AppendLineは、指定した文字列を追加したあとに改行を追加します。
大量の文字列を連結する場合、+演算子で何度も結合するより、StringBuilderを使った方が効率的です。
たとえば、ログやCSV、メール本文、レポート文書など、複数行のテキストを生成する場面でよく使われます。
C#StringBuilder sb = new StringBuilder();
sb.AppendLine("名前,年齢,部署");
sb.AppendLine("山田,30,営業");
sb.AppendLine("佐藤,28,開発");
string csv = sb.ToString();
なお、AppendLineで追加される改行は、基本的に環境に応じた改行です。改行コードを厳密に固定したい場合は、Appendで明示的に\nや\r\nを追加する方法もあります。
C#sb.Append("1行目\r\n");
sb.Append("2行目\r\n");
3-5. 逐語的文字列リテラルと複数行文字列の扱い
C#では、逐語的文字列リテラルを使って、ソースコード上の改行をそのまま文字列に含めることができます。
逐語的文字列リテラルは、文字列の前に@を付けて書きます。
C#string text = @"1行目
2行目
3行目";
Console.WriteLine(text);
この場合、ソースコード内の改行がそのまま文字列に含まれます。
ただし、実際に含まれる改行コードは、ソースファイルの改行コードやコンパイラの扱いに影響される場合があります。そのため、外部システム向けに厳密な改行コードが必要な場合は、\n、\r\n、Environment.NewLineなどを明示する方が安全です。
また、C# 11以降では、複数行の文字列を扱いやすい生文字列リテラルも使えます。
C#string text = """
1行目
2行目
3行目
""";
Console.WriteLine(text);
複数行のテンプレートやJSON、SQLなどを書くときに便利です。
C#string json = """
{
"name": "山田",
"age": 30
}
""";
ただし、これも改行コードを厳密に制御したい場合には注意が必要です。見た目上は複数行でも、内部の改行コードが処理対象の仕様と合っているか確認することが大切です。
4. Environment.NewLineの使い方と注意点
4-1. Environment.NewLineとは
Environment.NewLineは、現在の実行環境で使われる改行文字列を返すプロパティです。
C#string newLine = Environment.NewLine;
文字列の連結に使うと、環境に合わせた改行を入れることができます。
C#string text = "1行目" + Environment.NewLine + "2行目";
Environment.NewLineはメソッドではなくプロパティなので、後ろに()は付けません。
誤った書き方は次の通りです。
C#// 誤り
string newLine = Environment.NewLine();
正しくは次のように書きます。
C#// 正しい
string newLine = Environment.NewLine;
4-2. 実行環境によって返される改行コード
Environment.NewLineが返す値は、実行環境によって異なります。
一般的には、Windowsでは\r\n、LinuxやmacOSでは\nになります。
C#Console.WriteLine(Environment.NewLine == "\r\n");
Console.WriteLine(Environment.NewLine == "\n");
Windowsで実行すると、1つ目がTrueになりやすく、LinuxやmacOSでは2つ目がTrueになりやすいです。
そのため、同じC#のコードでも、実行するOSによって生成される文字列の改行コードが変わることがあります。
これは便利な反面、外部システムやファイル形式で改行コードが決まっている場合には注意が必要です。
4-3. \r\nや\nを直接書く場合との違い
\r\nや\nを直接書く場合、改行コードは常に固定されます。
C#string text1 = "1行目\r\n2行目"; // 常にCRLF
string text2 = "1行目\n2行目"; // 常にLF
一方、Environment.NewLineは実行環境によって変わります。
C#string text = "1行目" + Environment.NewLine + "2行目";
違いを整理すると、次のようになります。
\r\nを直接書く 常にWindows形式の改行
\nを直接書く 常にLF形式の改行
Environment.NewLine 実行環境に応じた改行
C#で改行コードを扱うときは、「環境に合わせたいのか」「特定の形式に固定したいのか」を考えることが重要です。
4-4. Environment.NewLineを使うべき場面
Environment.NewLineは、実行環境に合わせた自然な改行を使いたい場面に向いています。
たとえば、次のようなケースです。
コンソールアプリで複数行のメッセージを作る
OSに合わせたテキストファイルを生成する
ログやレポートをローカル環境向けに出力する
人が読むための文章を組み立てる
具体例は次の通りです。
C#string message =
"処理を開始しました。" + Environment.NewLine +
"しばらくお待ちください。" + Environment.NewLine +
"処理が完了しました。";
Console.WriteLine(message);
また、StringBuilderと組み合わせる場合も自然です。
C#StringBuilder sb = new StringBuilder();
sb.Append("名前: 山田");
sb.Append(Environment.NewLine);
sb.Append("部署: 開発部");
Console.WriteLine(sb.ToString());
実行環境ごとの標準的な改行コードを使いたい場合は、Environment.NewLineを選ぶとよいでしょう。
4-5. 固定の改行コードを使うべき場面
一方で、Environment.NewLineではなく、\r\nや\nを明示的に使うべき場面もあります。
たとえば、外部仕様で改行コードが決まっている場合です。
HTTPヘッダーではCRLFが必要
特定のCSV仕様でCRLFが指定されている
APIがLFのみを想定している
Git管理上、LFに統一したい
Linuxサーバーで処理するファイルをLFに統一したい
Windows向けファイルとしてCRLFに統一したい
このような場合にEnvironment.NewLineを使うと、実行環境によって出力結果が変わってしまいます。
たとえば、Windowsで実行すると\r\n、Linuxで実行すると\nになるため、同じコードでも生成されるファイルの内容が変わる可能性があります。
外部システムとの連携では、環境に合わせるよりも、仕様に合わせることが重要です。
C#// LFに固定したい場合
string text = "1行目\n2行目\n3行目";
// CRLFに固定したい場合
string textForWindows = "1行目\r\n2行目\r\n3行目";
特に、ファイル出力や通信データでは、求められる改行コードを確認してから実装しましょう。
5. C#で改行コードを置換・削除する方法
5-1. Replaceで\r\nを\nに置換する
Windows形式の改行コード\r\nを、LinuxやmacOSでよく使われる\nに変換したい場合は、Replaceを使います。
C#string text = "1行目\r\n2行目\r\n3行目";
string normalized = text.Replace("\r\n", "\n");
Console.WriteLine(normalized);
この処理により、CRLFがLFに変換されます。
ただし、文字列内に\r\nだけでなく、単独の\rも混在している場合は、追加の対応が必要です。
複数の改行コードをすべて\nに統一したい場合は、次のように書けます。
C#string text = "1行目\r\n2行目\r3行目\n4行目";
string normalized = text
.Replace("\r\n", "\n")
.Replace("\r", "\n");
Console.WriteLine(normalized);
ポイントは、先に\r\nを置換することです。
もし先に\rを置換すると、\r\nが意図しない形で処理されることがあります。
C#// 推奨
text.Replace("\r\n", "\n").Replace("\r", "\n");
改行コードを統一してからSplit('\n')などで行単位に処理すると、不具合を減らせます。
5-2. \nを\r\nに置換する
LF形式の改行コード\nを、Windows形式の\r\nに変換したい場合もReplaceを使えます。
ただし、単純に次のように書くと注意が必要です。
C#string converted = text.Replace("\n", "\r\n");
元の文字列にすでに\r\nが含まれている場合、この処理を行うと\r\r\nのように余計な\rが入ってしまう可能性があります。
安全にCRLFへ統一したい場合は、いったん改行コードを\nに正規化してから、\r\nへ変換する方法が分かりやすいです。
C#string text = "1行目\r\n2行目\r3行目\n4行目";
string normalized = text
.Replace("\r\n", "\n")
.Replace("\r", "\n");
string crlfText = normalized.Replace("\n", "\r\n");
Console.WriteLine(crlfText);
このように、まずすべての改行コードをLFに統一し、その後でCRLFに変換すると、混在した改行コードにも対応しやすくなります。
ファイル出力でWindows形式にそろえたい場合にも、この方法が有効です。
C#File.WriteAllText("output.txt", crlfText);
5-3. 改行コードをすべて削除する
文字列から改行コードをすべて削除したい場合も、Replaceを使います。
C#string text = "1行目\r\n2行目\n3行目\r4行目";
string removed = text
.Replace("\r\n", "")
.Replace("\n", "")
.Replace("\r", "");
Console.WriteLine(removed);
出力結果は次のようになります。
1行目2行目3行目4行目
改行を削除する場合も、\r\n、\n、\rのすべてを考慮することが大切です。
特に、Windows形式の\r\nだけを削除するコードでは、LFやCRが残る可能性があります。
C#// \r\nしか削除できない
string removed = text.Replace("\r\n", "");
複数の環境から受け取った文字列を処理する場合は、次のようにすべての改行パターンに対応する方が安全です。
C#string removed = text
.Replace("\r\n", "")
.Replace("\n", "")
.Replace("\r", "");
改行を半角スペースに置き換えたい場合は、空文字ではなくスペースを指定します。
C#string replaced = text
.Replace("\r\n", " ")
.Replace("\n", " ")
.Replace("\r", " ");
文章を1行にまとめたいときや、検索用の文字列を作るときに便利です。
まとめ
C#の改行コードを正しく扱うには、まず\r\n、\n、\rの違いを理解することが重要です。
Windowsでは主に\r\n、LinuxやmacOSでは主に\nが使われます。\rは現在の一般的なテキストファイルではあまり使われませんが、古い環境やコンソール制御などで登場することがあります。
C#で文字列に改行を入れる方法には、\nや\r\nを直接書く方法、Environment.NewLineを使う方法、Console.WriteLineやStringBuilder.AppendLineを使う方法があります。
実行環境に合わせた改行を使いたい場合は、Environment.NewLineが便利です。一方で、外部システムやファイル仕様で改行コードが決まっている場合は、\nや\r\nを明示的に指定する必要があります。
また、改行コードを置換・削除する場合は、\r\nだけでなく、\nや\rも考慮しましょう。特に複数の環境から受け取る文字列では、改行コードが混在している可能性があります。
C#で安定した文字列処理を行うためには、改行コードを意識し、必要に応じて正規化してから処理することが大切です。

