C#でログファイルを出力する方法|初心者向けに実装手順とサンプルコードを解説
はじめに
C#でアプリケーションを開発していると、処理の流れやエラー内容を後から確認したい場面がよくあります。そのようなときに役立つのが、ログファイルへの出力です。
ログファイルを残しておくと、プログラムがいつ実行されたのか、どの処理まで進んだのか、どのようなエラーが発生したのかを後から確認できます。特に、初心者のうちは「プログラムが動かない原因がわからない」という状況になりやすいため、ログ出力を覚えておくと開発やトラブル対応がしやすくなります。
この記事では、C#でログファイルを出力する基本から、日時付きログ、エラーログ、共通ログクラスの作り方まで、初心者にもわかりやすく解説します。
1. C#でログファイルを出力する基本
1-1. ログファイルとは何か
ログファイルとは、アプリケーションの動作内容やエラー情報を記録するためのファイルです。
たとえば、次のような内容をログファイルに残します。
2026-06-18 10:15:30 [INFO] アプリケーションを開始しました
2026-06-18 10:15:35 [INFO] ファイル読み込み処理を開始しました
2026-06-18 10:15:36 [ERROR] ファイルが見つかりません
このように、ログファイルには「いつ」「どの処理で」「何が起きたか」を記録します。C#では、標準のファイル操作機能を使って簡単にログファイルを作成できます。
1-2. C#でログ出力が必要になる場面
C#でログファイルへの出力が必要になる場面は多くあります。
たとえば、バッチ処理を実行した結果を残したい場合、WindowsフォームやWPFアプリでユーザー操作の履歴を確認したい場合、Webアプリケーションでエラーの原因を調査したい場合などです。
画面上では一瞬しか表示されない情報でも、ログファイルに保存しておけば後から確認できます。また、本番環境でエラーが発生した場合、ログがないと原因の特定が難しくなります。そのため、実務ではログ出力は非常に重要な機能です。
1-3. Console.WriteLineとの違い
C#初心者が最初に使う出力方法として、Console.WriteLineがあります。
C#Console.WriteLine("処理を開始しました");
Console.WriteLineは、コンソール画面に文字を表示するための命令です。一方、ログファイル出力は、文字列をテキストファイルに保存する処理です。
大きな違いは、情報が残るかどうかです。Console.WriteLineの表示内容は、コンソールを閉じると基本的に確認できなくなります。しかし、ログファイルに出力しておけば、アプリケーション終了後でも内容を確認できます。
開発中の簡単な確認にはConsole.WriteLineでも十分ですが、運用中の記録やエラー調査にはログファイル出力が向いています。
1-4. 初心者がまず理解すべきログ出力の流れ
C#でログファイルを出力する基本的な流れは、次のようになります。
まず、ログファイルの保存先を決めます。次に、ログに出力したいメッセージを作成します。そして、C#のファイル操作機能を使って、そのメッセージをファイルへ書き込みます。
基本的な考え方はとてもシンプルです。
ログメッセージを作る
↓
ログファイルのパスを決める
↓
ファイルに書き込む
この流れを理解しておけば、日時付きログやエラーログなどにも応用できます。
2. C#でログファイルを出力する前に準備すること
2-1. ログファイルの保存先を決める
ログファイルを出力する前に、まず保存先を決めておきましょう。
たとえば、アプリケーションの実行フォルダー内にlogsフォルダーを作成し、その中にログファイルを保存する方法があります。
アプリケーションフォルダー
└ logs
└ app.log
C#では、相対パスと絶対パスのどちらも使えます。
C#string logPath = "logs/app.log";
相対パスは簡単に指定できますが、実行場所によって保存先が変わることがあります。確実に保存先を管理したい場合は、アプリケーションの実行ディレクトリを基準にしたパスを作るとよいでしょう。
C#string logDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs");
string logPath = Path.Combine(logDirectory, "app.log");
2-2. ログに出力する内容を整理する
ログファイルには、何でも出力すればよいわけではありません。必要な情報を整理して出力することが大切です。
ログに出力する内容としては、次のようなものがあります。
処理開始・処理終了の情報
処理対象のファイル名
エラー内容
例外の詳細
ユーザー操作の内容
処理結果
ただし、パスワード、クレジットカード番号、個人情報、認証トークンなどの機密情報はログに出力しないように注意が必要です。
2-3. ファイル名と拡張子の決め方
ログファイルの拡張子には、一般的に.logや.txtを使います。
app.log
error.log
20260618.log
初心者の場合は、まずapp.logのようなわかりやすい名前で始めるとよいでしょう。日付ごとにログファイルを分けたい場合は、yyyyMMdd.logのように日付をファイル名に含めます。
C#string fileName = DateTime.Now.ToString("yyyyMMdd") + ".log";
日付ごとに分けることで、ログファイルが大きくなりすぎるのを防ぎやすくなります。
2-4. 文字コードと改行コードの基本
ログファイルを出力するときは、文字コードにも注意しましょう。
現在のC#では、UTF-8を使うのが一般的です。日本語をログに出力する場合でも、UTF-8を指定しておけば文字化けを防ぎやすくなります。
C#Encoding.UTF8
また、ログは1件ごとに改行して出力するのが基本です。C#では、Environment.NewLineを使うと実行環境に合った改行コードを使えます。
C#string message = "ログメッセージ" + Environment.NewLine;
3. C#でテキストファイルにログを出力する方法
3-1. File.WriteAllTextでログファイルを作成する
C#でログファイルを作成する最も簡単な方法のひとつが、File.WriteAllTextを使う方法です。
C#using System;
using System.IO;
using System.Text;
class Program
{
static void Main()
{
string path = "app.log";
string message = "ログファイルを作成しました";
File.WriteAllText(path, message, Encoding.UTF8);
}
}
このコードを実行すると、app.logというファイルが作成され、メッセージが書き込まれます。
ただし、File.WriteAllTextは既存のファイルがある場合、内容を上書きします。ログを追記したい場合には向いていません。
3-2. File.AppendAllTextでログを追記する
ログファイルには、通常、過去の内容を残したまま新しいログを追加します。その場合は、File.AppendAllTextを使います。
C#using System;
using System.IO;
using System.Text;
class Program
{
static void Main()
{
string path = "app.log";
string message = "ログを追記しました" + Environment.NewLine;
File.AppendAllText(path, message, Encoding.UTF8);
}
}
File.AppendAllTextは、ファイルが存在しない場合は新規作成し、存在する場合は末尾に追記します。そのため、ログ出力ではFile.AppendAllTextがよく使われます。
3-3. StreamWriterを使ってログを書き込む
StreamWriterを使うと、より柔軟にファイルへ書き込みできます。
C#using System;
using System.IO;
using System.Text;
class Program
{
static void Main()
{
string path = "app.log";
using (StreamWriter writer = new StreamWriter(path, true, Encoding.UTF8))
{
writer.WriteLine("StreamWriterでログを書き込みました");
}
}
}
StreamWriterの第2引数にtrueを指定すると追記モードになります。falseを指定すると上書きモードになります。
C#new StreamWriter(path, true, Encoding.UTF8)
ログを複数行まとめて出力したい場合や、細かく制御したい場合はStreamWriterが便利です。
3-4. using文でファイルを安全に閉じる
ファイルに書き込む処理では、使用したファイルを正しく閉じる必要があります。ファイルを閉じ忘れると、他の処理からファイルにアクセスできなくなることがあります。
C#では、using文を使うことで、処理が終わったあとに自動的にファイルを閉じられます。
C#using (StreamWriter writer = new StreamWriter("app.log", true, Encoding.UTF8))
{
writer.WriteLine("ログメッセージ");
}
初心者のうちは、StreamWriterを使うときは必ずusing文とセットで使う、と覚えておくと安全です。
3-5. ログ出力のサンプルコード
ここでは、C#でログファイルに文字列を追記する基本的なサンプルコードを紹介します。
C#using System;
using System.IO;
using System.Text;
class Program
{
static void Main()
{
string logDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs");
string logPath = Path.Combine(logDirectory, "app.log");
if (!Directory.Exists(logDirectory))
{
Directory.CreateDirectory(logDirectory);
}
string message = "アプリケーションを開始しました" + Environment.NewLine;
File.AppendAllText(logPath, message, Encoding.UTF8);
Console.WriteLine("ログを出力しました");
}
}
このコードでは、logsフォルダーが存在しない場合に作成し、その中のapp.logへログを追記しています。
4. 日時付きログを出力する実装手順
4-1. DateTimeを使って現在日時を取得する
ログファイルには、いつ処理が実行されたのかを記録するために日時を付けるのが基本です。
C#では、DateTime.Nowを使って現在日時を取得できます。
C#DateTime now = DateTime.Now;
ログ用に見やすい文字列へ変換する場合は、ToStringで書式を指定します。
C#string dateTimeText = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
この形式にすると、次のような日時になります。
2026-06-18 10:15:30
4-2. ログメッセージに日時を付ける
日時を取得したら、ログメッセージの先頭に付けます。
C#string log = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} 処理を開始しました";
実際にログファイルに出力すると、次のようになります。
2026-06-18 10:15:30 処理を開始しました
日時があることで、処理の順番やエラー発生時刻を確認しやすくなります。
4-3. ログレベルを付けて出力する
ログには、重要度を表すログレベルを付けることがあります。
代表的なログレベルには、INFO、WARN、ERRORがあります。
2026-06-18 10:15:30 [INFO] 処理を開始しました
2026-06-18 10:15:35 [WARN] 設定値が未入力です
2026-06-18 10:15:40 [ERROR] ファイル読み込みに失敗しました
ログレベルを付けることで、後からログを見たときに重要な情報を探しやすくなります。
4-4. INFO・WARN・ERRORの使い分け
INFOは、通常の処理状況を記録するときに使います。
[INFO] アプリケーションを開始しました
[INFO] ファイルの読み込みを開始しました
[INFO] 処理が正常に終了しました
WARNは、処理は継続できるものの注意が必要な場合に使います。
[WARN] 設定ファイルが存在しないため初期値を使用します
[WARN] 入力値が空です
ERRORは、処理に失敗した場合や例外が発生した場合に使います。
[ERROR] データベース接続に失敗しました
[ERROR] ファイルの読み込み中に例外が発生しました
初心者のうちは、通常の記録はINFO、注意はWARN、失敗や例外はERRORと覚えるとよいでしょう。
4-5. 日時付きログ出力のサンプルコード
次のコードは、日時とログレベルを付けてログファイルに出力するサンプルです。
C#using System;
using System.IO;
using System.Text;
class Program
{
static void Main()
{
WriteLog("INFO", "アプリケーションを開始しました");
WriteLog("INFO", "メイン処理を実行しました");
WriteLog("WARN", "設定値が未入力です");
WriteLog("ERROR", "エラーが発生しました");
}
static void WriteLog(string level, string message)
{
string logDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs");
string logPath = Path.Combine(logDirectory, "app.log");
if (!Directory.Exists(logDirectory))
{
Directory.CreateDirectory(logDirectory);
}
string logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{level}] {message}{Environment.NewLine}";
File.AppendAllText(logPath, logMessage, Encoding.UTF8);
}
}
このようにメソッド化しておくと、ログを出力したい場所から簡単に呼び出せます。
5. エラー内容をログファイルに出力する方法
5-1. try-catchで例外を捕捉する
C#でエラー内容をログファイルに出力するには、try-catchを使います。
C#try
{
// エラーが発生する可能性のある処理
}
catch (Exception ex)
{
// エラー発生時の処理
}
tryブロックには通常の処理を書き、catchブロックには例外が発生したときの処理を書きます。エラー内容をログファイルへ出力する場合は、catchの中でログ出力処理を呼び出します。
5-2. Exception.Messageをログに出力する
例外の内容を確認するには、Exception.Messageを使います。
C#catch (Exception ex)
{
string errorMessage = ex.Message;
}
ex.Messageには、例外の概要が入っています。たとえば、ファイルが見つからない場合は、その内容を示すメッセージを取得できます。
C#WriteLog("ERROR", ex.Message);
ただし、Messageだけでは原因調査に必要な情報が不足することがあります。
5-3. StackTraceを出力して原因調査に役立てる
エラーの発生場所を詳しく確認したい場合は、StackTraceもログに出力します。
C#catch (Exception ex)
{
WriteLog("ERROR", ex.Message);
WriteLog("ERROR", ex.StackTrace);
}
StackTraceには、例外が発生したメソッドや行番号に関する情報が含まれることがあります。開発中や障害調査では非常に役立ちます。
ただし、本番環境で詳細すぎる情報を出力すると、内部構造がログに残る可能性があります。運用ルールに合わせて出力内容を調整しましょう。
5-4. エラーログ出力のサンプルコード
次のコードは、存在しないファイルを読み込もうとして例外が発生した場合に、エラー内容をログファイルへ出力する例です。
C#using System;
using System.IO;
using System.Text;
class Program
{
static void Main()
{
try
{
string text = File.ReadAllText("notfound.txt");
Console.WriteLine(text);
}
catch (Exception ex)
{
WriteLog("ERROR", "ファイル読み込み中にエラーが発生しました");
WriteLog("ERROR", ex.Message);
WriteLog("ERROR", ex.StackTrace ?? "");
}
}
static void WriteLog(string level, string message)
{
string logDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs");
string logPath = Path.Combine(logDirectory, "error.log");
if (!Directory.Exists(logDirectory))
{
Directory.CreateDirectory(logDirectory);
}
string logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{level}] {message}{Environment.NewLine}";
File.AppendAllText(logPath, logMessage, Encoding.UTF8);
}
}
このコードを実行すると、logsフォルダー内のerror.logにエラー内容が記録されます。
5-5. 例外発生時にログ出力で注意すべきこと
例外発生時にログを出力するときは、ログ出力処理自体でさらに例外が発生する可能性にも注意が必要です。
たとえば、ログフォルダーに書き込み権限がない場合、ログファイルへの書き込みでエラーになることがあります。
そのため、重要なアプリケーションでは、ログ出力処理の中でも例外対策をしておくと安心です。
C#try
{
File.AppendAllText(logPath, logMessage, Encoding.UTF8);
}
catch
{
// ログ出力失敗時の処理
}
ただし、catchの中で何でも無視してしまうと問題に気づけないこともあります。開発中はコンソールに表示するなど、状況に応じて対応しましょう。
6. ログ出力処理を共通化する方法
6-1. ログ出力用メソッドを作成する
ログ出力のコードを毎回書くと、プログラム内で同じ処理が何度も登場してしまいます。そこで、ログ出力用のメソッドを作成して共通化します。
C#static void WriteLog(string message)
{
string logPath = "app.log";
string logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} {message}{Environment.NewLine}";
File.AppendAllText(logPath, logMessage, Encoding.UTF8);
}
このようにしておけば、ログを出力したい場所で次のように呼び出せます。
C#WriteLog("処理を開始しました");
共通化することで、ログの形式を変更したい場合も1か所を修正するだけで済みます。
6-2. ログレベルを引数で切り替える
ログレベルも引数で渡せるようにすると便利です。
C#static void WriteLog(string level, string message)
{
string logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{level}] {message}{Environment.NewLine}";
File.AppendAllText("app.log", logMessage, Encoding.UTF8);
}
呼び出し側では、次のように使えます。
C#WriteLog("INFO", "処理を開始しました");
WriteLog("WARN", "設定値が空です");
WriteLog("ERROR", "例外が発生しました");
ログレベルを統一しておくと、後から検索や分析がしやすくなります。
6-3. ログファイル名を日付ごとに分ける
ログファイルを日付ごとに分けると、管理しやすくなります。
C#string fileName = $"{DateTime.Now:yyyyMMdd}.log";
たとえば、2026年6月18日のログであれば、次のようなファイル名になります。
20260618.log
日付ごとにファイルを分けると、ログファイルの肥大化を防ぎやすくなります。また、特定の日に発生したエラーを探しやすくなります。
6-4. 共通ログクラスを作成する
より再利用しやすくするには、ログ出力専用のクラスを作成します。
たとえば、Loggerクラスを作っておけば、アプリケーションのさまざまな場所から同じ方法でログを出力できます。
C#Logger.Info("処理を開始しました");
Logger.Warn("設定値が未入力です");
Logger.Error("エラーが発生しました");
ログクラスを作るメリットは、ログ出力の形式や保存先を一元管理できることです。後からログの形式を変更したい場合も、ログクラスだけを修正すれば済みます。
6-5. 再利用しやすいログ出力クラスのサンプルコード
次のコードは、C#で使えるシンプルな共通ログクラスの例です。
C#using System;
using System.IO;
using System.Text;
public static class Logger
{
private static readonly object _lock = new object();
public static void Info(string message)
{
Write("INFO", message);
}
public static void Warn(string message)
{
Write("WARN", message);
}
public static void Error(string message)
{
Write("ERROR", message);
}
public static void Error(Exception ex)
{
Write("ERROR", ex.Message);
Write("ERROR", ex.StackTrace ?? "");
}
private static void Write(string level, string message)
{
try
{
string logDirectory = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "logs");
string fileName = $"{DateTime.Now:yyyyMMdd}.log";
string logPath = Path.Combine(logDirectory, fileName);
if (!Directory.Exists(logDirectory))
{
Directory.CreateDirectory(logDirectory);
}
string logMessage = $"{DateTime.Now:yyyy-MM-dd HH:mm:ss} [{level}] {message}{Environment.NewLine}";
lock (_lock)
{
File.AppendAllText(logPath, logMessage, Encoding.UTF8);
}
}
catch
{
// ログ出力に失敗した場合は必要に応じて別の対応を行う
}
}
}
使い方は次のとおりです。
C#class Program
{
static void Main()
{
Logger.Info("アプリケーションを開始しました");
try
{
string text = File.ReadAllText("sample.txt");
Logger.Info("ファイルを読み込みました");
}
catch (Exception ex)
{
Logger.Error(ex);
}
Logger.Info("アプリケーションを終了しました");
}
}
このようなログクラスを用意しておくと、C#のさまざまなプロジェクトで再利用できます。
7. ログファイル出力でよくあるエラーと対処法
7-1. ファイルパスが見つからない場合の対処法
ログ出力でよくあるエラーのひとつが、保存先フォルダーが存在しないケースです。
たとえば、logs/app.logに書き込もうとしても、logsフォルダーが存在しないとエラーになることがあります。
対処法として、ログ出力前にフォルダーの存在を確認し、なければ作成します。
C#if (!Directory.Exists(logDirectory))
{
Directory.CreateDirectory(logDirectory);
}
ログファイルを出力するときは、ファイルだけでなくフォルダーの存在も確認しましょう。
7-2. アクセス権限エラーが出る場合の対処法
ログファイルの保存先によっては、書き込み権限がなくエラーになることがあります。
たとえば、C:\Program Files配下などは、通常のユーザー権限では書き込めない場合があります。
このような場合は、アプリケーションが書き込み可能なフォルダーにログを保存しましょう。開発中であれば、アプリケーションの実行フォルダー内やユーザーフォルダー配下を使うと扱いやすいです。
C#string logDirectory = Path.Combine(
Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData),
"MyApp",
"logs"
);
このように、ユーザーごとのアプリケーションデータフォルダーを利用する方法もあります。
7-3. ファイルが使用中で書き込めない場合の対処法
複数の処理が同時に同じログファイルへ書き込むと、ファイルが使用中となりエラーが発生することがあります。
簡単な対策としては、lockを使って同時書き込みを防ぎます。
C#private static readonly object _lock = new object();
lock (_lock)
{
File.AppendAllText(logPath, logMessage, Encoding.UTF8);
}
ただし、複数のプロセスから同じログファイルへ書き込む場合は、さらに慎重な設計が必要です。そのような場合は、NLogやSerilogなどのログ出力ライブラリを使うことも検討しましょう。
7-4. 文字化けが発生する場合の対処法
ログファイルに日本語を出力したときに文字化けする場合は、文字コードを確認しましょう。
C#でログ出力するときは、UTF-8を指定するのがおすすめです。
C#File.AppendAllText(logPath, logMessage, Encoding.UTF8);
また、ログファイルを開くエディタ側の文字コード設定も確認してください。ファイルはUTF-8で出力されているのに、エディタが別の文字コードとして開いていると文字化けして見えることがあります。
7-5. ログが追記されず上書きされる場合の確認点
ログが追記されず、毎回上書きされてしまう場合は、使用しているメソッドを確認しましょう。
File.WriteAllTextはファイルを上書きします。
C#File.WriteAllText(logPath, logMessage, Encoding.UTF8);
追記したい場合は、File.AppendAllTextを使います。
C#File.AppendAllText(logPath, logMessage, Encoding.UTF8);
StreamWriterを使う場合は、第2引数がtrueになっているか確認します。
C#using (StreamWriter writer = new StreamWriter(logPath, true, Encoding.UTF8))
{
writer.WriteLine(logMessage);
}
8. C#でログファイルを出力するときの注意点
8-1. 個人情報や機密情報をログに出力しない
ログファイルには、個人情報や機密情報を出力しないようにしましょう。
たとえば、次のような情報はログに出力すべきではありません。
パスワード
クレジットカード番号
認証トークン
個人番号
住所や電話番号
メールアドレス
ログは開発者や運用担当者が確認することがあります。また、障害調査のために共有される場合もあります。不要な情報を出力しないことが、安全なログ運用の基本です。
8-2. ログファイルの肥大化を防ぐ
ログを出力し続けると、ログファイルはどんどん大きくなります。ファイルサイズが大きくなりすぎると、ディスク容量を圧迫したり、ログの確認に時間がかかったりします。
初心者向けの簡単な対策としては、ログファイルを日付ごとに分ける方法があります。
20260618.log
20260619.log
20260620.log
本格的なアプリケーションでは、一定サイズを超えたらファイルを分割するローテーション機能を使うこともあります。
8-3. ログ保存期間を決めておく
ログファイルは、いつまでも保存し続けるのではなく、保存期間を決めておくことが大切です。
たとえば、開発環境では7日間、本番環境では30日間や90日間など、運用ルールに合わせて決めます。
古いログを削除する処理を自作することもできますが、初心者のうちはまず「ログは増え続けるもの」と理解し、定期的に整理する意識を持つことが大切です。
8-4. 本番環境と開発環境でログ内容を分ける
開発環境では、原因調査のために詳細なログを出力したいことがあります。一方、本番環境では、ログを出しすぎるとファイルサイズが大きくなったり、機密情報が残るリスクが高まったりします。
そのため、開発環境では詳細ログを出し、本番環境では必要な情報だけを出すように分けるとよいでしょう。
たとえば、開発中はINFOやDEBUGを多めに出し、本番環境ではWARNやERRORを中心に出力する設計が考えられます。
8-5. 読みやすいログ形式に整える
ログファイルは、人が読んで原因を調査するためのものでもあります。そのため、形式を統一して読みやすくすることが重要です。
おすすめの形式は、次のような形です。
日時 [ログレベル] メッセージ
例としては、次のようになります。
2026-06-18 10:15:30 [INFO] 処理を開始しました
2026-06-18 10:15:35 [ERROR] ファイル読み込みに失敗しました
日時、ログレベル、メッセージの順番を統一するだけでも、ログはかなり読みやすくなります。
9. ログ出力ライブラリを使う選択肢
9-1. 標準機能だけで実装する場合のメリット
C#では、File.AppendAllTextやStreamWriterなどの標準機能だけでもログファイルを出力できます。
標準機能だけで実装するメリットは、仕組みがわかりやすいことです。外部ライブラリを追加する必要がないため、初心者でも始めやすいです。
また、小規模なツールや学習用プログラムであれば、標準機能だけでも十分な場合があります。
一方で、ログローテーション、非同期出力、複数出力先への対応、ログレベルの細かい制御などを自作するのは手間がかかります。
9-2. NLogを使う場合の特徴
NLogは、C#でよく使われるログ出力ライブラリのひとつです。
ファイル出力、コンソール出力、ログレベルの制御、ログファイルのローテーションなど、多くの機能を設定ファイルやコードで管理できます。
標準機能だけで実装するよりも高機能で、実務向けのログ出力を作りやすいのが特徴です。
ログの保存先やフォーマットを柔軟に変更したい場合に向いています。
9-3. log4netを使う場合の特徴
log4netも、C#で使われてきた代表的なログ出力ライブラリです。
Javaのlog4jに近い考え方を持っており、長く使われている実績があります。既存のシステムでlog4netが採用されていることもあります。
設定によって、ファイル、コンソール、データベースなどにログを出力できます。既存プロジェクトで使われている場合は、そのルールに合わせて利用するとよいでしょう。
9-4. Serilogを使う場合の特徴
Serilogは、構造化ログに強いログ出力ライブラリです。
通常の文字列ログだけでなく、プロパティを持ったログを出力しやすいのが特徴です。たとえば、ユーザーIDや処理IDなどをログに含めて、後から検索しやすくできます。
Webアプリケーションやクラウド環境でのログ分析にも向いています。
見やすいログを出すだけでなく、後から検索・集計しやすいログを作りたい場合に便利です。
9-5. 初心者は標準機能とライブラリのどちらを選ぶべきか
初心者がC#でログファイル出力を学ぶ場合、まずは標準機能で実装するのがおすすめです。
File.AppendAllTextやStreamWriterを使ってログを出力すると、ファイル書き込みの基本やログの仕組みを理解できます。
そのうえで、実務や本格的なアプリケーションでは、NLog、log4net、Serilogなどのライブラリを検討するとよいでしょう。
学習の順番としては、次の流れがおすすめです。
File.AppendAllTextで基本を理解する
↓
StreamWriterでファイル書き込みを理解する
↓
共通ログクラスを作る
↓
必要に応じてログライブラリを使う
10. C#のログファイル出力に関するよくある質問
10-1. ログファイルの保存場所はどこがよいか
開発中であれば、アプリケーションの実行フォルダー内にlogsフォルダーを作成して保存する方法がわかりやすいです。
logs/app.log
本番環境では、アプリケーションが書き込み可能で、運用担当者が確認しやすい場所に保存します。
Windowsアプリの場合は、ユーザーごとのアプリケーションデータフォルダーを使う方法もあります。
C#Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData)
重要なのは、書き込み権限があり、管理しやすい場所を選ぶことです。
10-2. ログファイルは毎日分けたほうがよいか
ログの量が少ない小規模なアプリケーションであれば、ひとつのログファイルでも問題ない場合があります。
しかし、実務では日付ごとにログファイルを分けることがよくあります。日付ごとに分けると、ファイルサイズが大きくなりすぎるのを防ぎやすく、特定の日のログを探しやすくなります。
初心者の場合も、最初から日付ごとのログファイルにしておくと管理しやすいです。
C#string fileName = $"{DateTime.Now:yyyyMMdd}.log";
10-3. ログ出力は非同期にしたほうがよいか
小規模なアプリケーションや学習用のプログラムであれば、まずは同期処理で問題ありません。
C#File.AppendAllText(logPath, logMessage, Encoding.UTF8);
ただし、大量のログを出力するアプリケーションでは、ログ出力が処理速度に影響することがあります。その場合は、非同期処理やログライブラリの利用を検討します。
初心者は、最初から非同期処理にこだわるよりも、まずは正しくログを出力できることを優先しましょう。
10-4. WindowsフォームやWPFでも同じ方法で使えるか
WindowsフォームやWPFでも、基本的なログファイル出力の方法は同じです。
File.AppendAllTextやStreamWriterは、コンソールアプリだけでなく、Windowsフォーム、WPF、クラスライブラリなどでも利用できます。
たとえば、ボタンをクリックしたときにログを出力することもできます。
C#private void Button_Click(object sender, EventArgs e)
{
Logger.Info("ボタンがクリックされました");
}
画面アプリでは、ユーザー操作やエラー内容をログに残しておくと、不具合調査に役立ちます。
10-5. ログが出力されないときは何を確認すべきか
ログが出力されない場合は、まず保存先のパスを確認しましょう。
相対パスを使っている場合、想定していた場所とは違うフォルダーにログファイルが作成されていることがあります。AppDomain.CurrentDomain.BaseDirectoryを使って、実行フォルダーを確認するとよいです。
次に、ログフォルダーが存在するか、書き込み権限があるかを確認します。
また、File.WriteAllTextで上書きしていないか、File.AppendAllTextを使っているかも確認しましょう。
確認すべきポイントは次のとおりです。
ログファイルの保存先パスは正しいか
保存先フォルダーは存在するか
書き込み権限はあるか
例外が発生していないか
追記ではなく上書きになっていないか
文字コードは適切か
まとめ
C#でログファイルを出力するには、File.AppendAllTextやStreamWriterを使うのが基本です。
初心者は、まずテキストファイルにログを追記する方法を覚えましょう。そのうえで、日時、ログレベル、エラー内容を追加していくと、実用的なログファイルを作成できます。
特に重要なのは、次のポイントです。
ログファイルには処理状況やエラー内容を記録する
Console.WriteLineと違い、ログファイルは後から確認できる
追記にはFile.AppendAllTextを使う
StreamWriterを使う場合はusing文で安全に閉じる
日時とログレベルを付けると読みやすくなる
例外発生時はException.MessageやStackTraceを記録する
ログ出力処理は共通メソッドやクラスにまとめる
個人情報や機密情報はログに出力しない
ログファイルの肥大化を防ぐため日付ごとに分ける
必要に応じてNLog、log4net、Serilogなどのライブラリを使う
C#のログファイル出力は、難しい機能に見えるかもしれませんが、基本は文字列をファイルに書き込むだけです。まずはシンプルなログ出力から始めて、少しずつ日時付きログ、エラーログ、共通ログクラスへ発展させていきましょう。

