ここでは、指定した文字列に、ファイル名やフォルダ名(以下、ファイル名)に使用できない文字や文字列が含まれていないか調べる方法を紹介します。
しかしここで紹介している方法は完全な方法ではありませんので、本当にそのファイル名でファイルを作成できるかは、実際にファイルを作成してみることでしか確認できないでしょう。
なお、ファイル名に使用できない文字が含まれている場合これをすべて削除する方法は、「文字列から指定した文字を削除する」を参考にしてください。
ファイル名に使用できない文字は、Path.GetInvalidFileNameCharsメソッドで取得できます。また、ファイルのパスに使用できない文字は、Path.GetInvalidPathCharsメソッドで取得できます。
これらのメソッドは.NET Framework 2.0以降でしか使用できませんので、それ未満であれば、代わりにPath.InvalidPathCharsフィールド(Path.GetInvalidPathCharsメソッドと同等)を使います。
具体的には、GetInvalidPathChars内の文字は、1~31のASCII/Unicode文字、引用符(")、不等号(<と>)、パイプ(|)、null(\0)の36文字になります。GetInvalidFileNameCharsはこれに加えて、コロン(:)、アスタリスク(*)、クエスチョンマーク(?)、スラッシュ(/)、バックスラッシュ(\)の41文字になります。
ただし、ヘルプには、「ファイル名やディレクトリ名としては無効なすべての文字が含まれるかどうかは、保証されません。」と無責任なことが書かれていますので、これだけを信用することはできません。
以下にGetInvalidFileNameCharsメソッドを使ってファイル名に使用できない文字が含まれていないか調べる例を示します。.NET Framework 2.0以降で実行可能です。
'調べるファイル名 Dim fileName As String = "abc.txt" 'ファイル名に使用できない文字を取得 Dim invalidChars As Char() = System.IO.Path.GetInvalidFileNameChars() If fileName.IndexOfAny(invalidChars) < 0 Then Console.WriteLine("ファイル名に使用できない文字は使われていません。") Else Console.WriteLine("ファイル名に使用できない文字が使われています。") End If
//調べるファイル名 string fileName = "abc.txt"; //ファイル名に使用できない文字を取得 char[] invalidChars = System.IO.Path.GetInvalidFileNameChars(); if (fileName.IndexOfAny(invalidChars) < 0) { Console.WriteLine("ファイル名に使用できない文字は使われていません。"); } else { Console.WriteLine("ファイル名に使用できない文字が使われています。"); }
「Naming Files, Paths, and Namespaces」によると、ファイル名に使用できない名前は、先に紹介した文字を含んだ名前の他に、以下のようなものがあります。
これに加えて、「CLOCK$」、「COM0」、「LPT0」も使用できないという話もあります。(私がWindows 8.1で試した限りでは、「CLOCK$」はエクスプローラで作成できました。また、拡張子があれば、「CLOCK$」を使用できるという話もあります。)
以上の情報を基に、不正なファイル名を正規表現で調べるサンプルを作ってみました。
'確認したいファイル名 Dim f As String = "test.txt" '不正なファイル名をチェックする正規表現 Dim r As New System.Text.RegularExpressions.Regex( _ "[\x00-\x1f<>:""/\\|?*]" & _ "|^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9]|CLOCK\$)(\.|$)" & _ "|[\. ]$", _ System.Text.RegularExpressions.RegexOptions.IgnoreCase) 'マッチしたら、不正なファイル名 If r.IsMatch(f) Then Console.WriteLine("不正なファイル名です。") End If
//確認したいファイル名 string f = "test.txt"; //不正なファイル名をチェックする正規表現 System.Text.RegularExpressions.Regex r = new System.Text.RegularExpressions.Regex( "[\\x00-\\x1f<>:\"/\\\\|?*]" + "|^(CON|PRN|AUX|NUL|COM[0-9]|LPT[0-9]|CLOCK\\$)(\\.|$)" + "|[\\. ]$", System.Text.RegularExpressions.RegexOptions.IgnoreCase); //マッチしたら、不正なファイル名 if (r.IsMatch(f)) { Console.WriteLine("不正なファイル名です。"); }
Path.GetFullPathメソッドは、指定されたパスが正しいかをある程度調べ、不正と判断した場合は、例外をスローします。例えば、パスに使用できない文字が含まれている場合はArgumentException、アクセス許可がない場合はSecurityException、ボリューム識別子(「C:\」など)以外に「:」がある場合はNotSupportedException、パスの長さが長すぎる(フルパスの長さが260文字以上)場合はPathTooLongExceptionがスローされます。
Path.GetFullPathメソッド以外にも、FileInfoコンストラクタなどを使っても、ほぼ同じことができます。
この方法は例外を発生させることで調べるため、あまり良い方法とは言えないでしょう。
以下に、この方法を使ってファイル名が正しいか調べるメソッドの例を示します。
''' <summary> ''' 指定されたファイル名に不正がないかチェックする ''' </summary> ''' <param name="fileName">チェックするファイル名。</param> ''' <returns>不正がないと判断された場合は、True。それ以外は、False。</returns> Public Shared Function IsValidFileName(fileName As String) As Boolean Try 'GetFullPathメソッドに渡して、例外がスローされるか確かめる System.IO.Path.GetFullPath(fileName) Catch ex As ArgumentException 'ファイル名に不正な文字が含まれている場合など Return False Catch ex As System.Security.SecurityException 'アクセスできない場合 Return False Catch ex As NotSupportedException 'ボリューム識別子以外に「:」がある場合 Return False Catch ex As System.IO.PathTooLongException 'パス名が長すぎる場合 Return False End Try Return True End Function
/// <summary> /// 指定されたファイル名に不正がないかチェックする /// </summary> /// <param name="fileName">チェックするファイル名。</param> /// <returns>不正がないと判断された場合は、True。それ以外は、False。</returns> public static bool IsValidFileName(string fileName) { try { //GetFullPathメソッドに渡して、例外がスローされるか確かめる System.IO.Path.GetFullPath(fileName); } catch (ArgumentException) { //ファイル名に不正な文字が含まれている場合など return false; } catch (System.Security.SecurityException) { //アクセスできない場合 return false; } catch (NotSupportedException) { //ボリューム識別子以外に「:」がある場合 return false; } catch (System.IO.PathTooLongException) { //パス名が長すぎる場合 return false; } return true; }