MRが楽しい

MRやVRについて学習したことを書き残す

ファイルまたはフォルダ作成時にWindowsで利用不可なファイル名かチェックする

本日はC#の小ネタ枠です。
ファイルまたはフォルダ作成時にWindowsで利用不可なファイル名かチェックする方法です。

Windowsのファイル名の命名規則

Windowsのファイル名には利用不可能な予約文字や予約名が存在します。
これらを含むファイル名は通常利用できず、何らかの要因で誤って利用した場合問題が発生することがあります。
learn.microsoft.com

例えばWindowsで利用不可な予約文字は以下の通りです。

< (より小さい)
> (より大きい)
: (コロン)
" (二重引用符)
/ (スラッシュ)
\ (円記号)
| (縦棒またはパイプ)
? (疑問符)
* (アスタリスク)

利用不可な予約名は以下の通りです。

CON、PRN、AUX、NUL、
COM0、COM1、COM2、COM3、COM4、COM5、COM6、COM7、COM8、COM9、COM¹、COM²、COM³、
LPT0、LPT1、LPT2、LPT3、LPT4、LPT5、LPT6、LPT7、LPT8、LPT9、LPT¹、LPT²、LPT³

サンプルスクリプト

これらの利用不可なファイル名かチェックを行う以下のサンプルスクリプトを作成しました。
・FileNameCheckTest2.cs

using System;
using System.IO;
using UnityEngine;

public class FileNameCheckTest2 : MonoBehaviour
{
    /// <summary>
    /// 作成するファイル名
    /// </summary>
    [SerializeField]
    private string fileName = default;
    
    private string DocumentFolderPath => System.Environment.GetFolderPath(System.Environment.SpecialFolder.MyDocuments);
    
    /// <summary>
    /// ファイル名で利用不可なWindowsのファイルシステムの予約文字
    /// </summary>
    private static readonly char[] InvalidFileNameCharsWindows = new Char[]
    {
        '<', '>', ':', '"', '/', '\\', '|', '?', '*'
    };

    /// <summary>
    /// ファイル名で利用不可なWindowsのファイルシステムの予約ファイル名
    /// </summary>
    private static readonly string[] InvalidFileNameWindows = new string[]
    {
        "CON", "PRN", "AUX", "NUL",
        "COM0", "COM1", "COM2", "COM3", "COM4", "COM5", "COM6", "COM7", "COM8", "COM9", "COM¹", "COM²", "COM³",
        "LPT0", "LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9", "LPT¹", "LPT²", "LPT³"
    };
    
    // ファイルを作成する
    [ContextMenu("CreateFile")]
    public void CreateFile()
    {
        // ファイル名に利用不可なファイルシステムの予約文字が含まれているか確認する
        if (fileName.IndexOfAny(InvalidFileNameCharsWindows) >= 0)
        {
            Debug.LogError($"Invalid FileName: {fileName}");
            return;
        }
        
        // 予約ファイル名のチェックは拡張子を除いたファイル名で行う
        // 英字の大文字小文字は区別しないため、大文字に変換してから検索する
        var fileNameWithoutExtension = Path.GetFileNameWithoutExtension(fileName).ToUpper();
        
        // ファイル名が利用不可なファイルシステムの予約ファイル名か確認する
        if (Array.Exists(InvalidFileNameWindows, x => x == fileNameWithoutExtension))
        {
            Debug.LogError($"Invalid FileName: {fileName}");
            return;
        }
        
        // ファイルが存在しない場合はファイルを作成する
        var fileFolderPath = Path.Combine(DocumentFolderPath, "ScriptTest");
        var newFilePath = Path.Combine(fileFolderPath, "newFile.txt");
        if (!File.Exists(newFilePath)) File.Create(newFilePath).Close();
        Debug.Log($"Create File: {newFilePath}");
    }
}

利用不可なファイル名を指定した場合、エラーメッセージを返してファイルを作成しません。