--- 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`