---
lang: ja-jp
breaks: true
---
# C# Windows で ファイル名として使用できない文字列をノーマライズする 2025-10-03
```csharp=
using System;
using System.IO;
using System.Linq;
using System.Text;
public static class FileNameNormalizer
{
// Windowsの予約語リスト
private static readonly string[] ReservedWords =
{
"CON", "PRN", "AUX", "NUL",
"COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9",
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9"
};
// ファイル名に使えない文字を取得
private static HashSet<char> InvalidFileNameChars = new HashSet<char>(Path.GetInvalidFileNameChars());
/// <summary>
/// 指定された文字列をファイル名として使用できる形式にノーマライズします。
/// </summary>
/// <param name="filename">ノーマライズする文字列。</param>
/// <param name="replacement">無効な文字の代替として使用する文字列。デフォルトは"_"です。</param>
/// <param name="default_filename">無効な場合に使用するデフォルトのファイル名。</param>
/// <returns>ノーマライズされたファイル名。</returns>
public static string Normalize(
string filename,
string replacement = "_",
string default_filename = ""
)
{
if (string.IsNullOrEmpty(filename))
{
return default_filename;
}
var sb = new StringBuilder();
foreach (char c in filename)
{
// 使用できない文字は代替文字に置換
if (InvalidFileNameChars.Contains(c))
{
sb.Append(replacement);
}
else
{
sb.Append(c);
}
}
string normalized = sb.ToString();
// 末尾のピリオドやスペースはWindowsによって無視されるため、取り除く
normalized = normalized.TrimEnd('.', ' ');
// 予約語と完全に一致するかチェック(大文字・小文字を区別しない)
if (ReservedWords.Contains(normalized.ToUpper()))
{
normalized = "_" + normalized;
}
// 全て無効な文字だった場合などを考慮
if (string.IsNullOrWhiteSpace(normalized))
{
return default_filename;
}
return normalized;
}
}
// 使用例
public class Program
{
public static void Main()
{
string originalName1 = "My*File?/Name<>.txt";
string normalizedName1 = FileNameNormalizer.Normalize(originalName1);
Console.WriteLine($"'{originalName1}' -> '{normalizedName1}'"); // 'My*File?/Name<>.txt' -> 'My_File__Name__.txt'
string originalName2 = "CON";
string normalizedName2 = FileNameNormalizer.Normalize(originalName2);
Console.WriteLine($"'{originalName2}' -> '{normalizedName2}'"); // 'CON' -> '_CON'
string originalName3 = "file_name_with_space. ";
string normalizedName3 = FileNameNormalizer.Normalize(originalName3);
Console.WriteLine($"'{originalName3}' -> '{normalizedName3}'"); // 'file_name_with_space. ' -> 'file_name_with_space'
}
}
```
:::info
`Path.GetInvalidFileNameChars()` が返す無効な文字のリストに、サロゲート文字自体が含まれていることは通常ないので、上記の処理で問題ないはずです。
:::
###### tags: `C#` `Windows` `ファイル名` `ノーマライズ` `Normalize`