web-dev-qa-db-ja.com

C#で、ファイル名が(おそらく)有効であることを確認します(存在しないこと)

System.IO名前空間にファイル名の有効性をチェックするメソッドはありますか?

たとえば、C:\foo\barは検証され、:"~-*は検証されません

または少し複雑です。X:\foo\barはシステムにX:ドライブが存在することを検証しますが、そうでない場合は検証しません。

私はそのようなメソッドを自分で書くことができると思いますが、組み込みのメソッドにもっと興味があります。

122
scru

ただやる

System.IO.FileInfo fi = null;
try {
  fi = new System.IO.FileInfo(fileName);
}
catch (ArgumentException) { }
catch (System.IO.PathTooLongException) { }
catch (NotSupportedException) { }
if (ReferenceEquals(fi, null)) {
  // file name is not valid
} else {
  // file name is valid... May check for existence by calling fi.Exists.
}

FileInfoインスタンスを作成するために、ファイルは存在する必要はありません。

91
mmmmmmmm

Path.GetInvalidPathChars および GetInvalidFileNameChars から無効な文字のリストを取得できます この質問

Jbergerが述べたように、このメソッドからの応答に含まれていない他の文字がいくつかあります。 Windowsプラットフォームの詳細については、MSDNの ファイル、パス、名前空間の命名 をご覧ください。

Micah points out のように、有効なドライブのリストを取得するために Directory.GetLogicalDrives があります。

34
Eugene Katz

System.Uriクラスを使用できます。 UriクラスはWeb URLだけでなく、ファイルシステムパスも処理します。 Uri.TryCreateメソッドを使用して、パスがルート化されているかどうかを確認し、IsLoopbackプロパティを使用して、Uriがローカルマシンを参照しているかどうかを判断します。

以下は、文字列が有効な、ローカルで、ルート化されたファイルパスであるかどうかを判断する簡単な方法です。

public bool IsPathValidRootedLocal(String pathString) {
    Uri pathUri;
    Boolean isValidUri = Uri.TryCreate(pathString, UriKind.Absolute, out pathUri);
    return isValidUri && pathUri != null && pathUri.IsLoopback;
}

これが機能すると確信しています。

11
LamdaComplex

System.IO名前空間に存在する使用可能なメソッドがいくつかあります。

Directory.GetLogicalDrives() // Returns an array of strings like "c:\"
Path.GetInvalidFileNameChars() // Returns an array of characters that cannot be used in a file name
Path.GetInvalidPathChars() // Returns an array of characters that cannot be used in a path.

提案されたように、これを行うことができます:

bool IsValidFilename(string testName) {
    string regexString = "[" + Regex.Escape(Path.GetInvalidPathChars()) + "]";
    Regex containsABadCharacter = new Regex(regexString);
    if (containsABadCharacter.IsMatch(testName)) {
        return false;
    }

    // Check for drive
    string pathRoot = Path.GetPathRoot(testName);
    if (Directory.GetLogicalDrives().Contains(pathRoot)) {
        // etc
    }

    // other checks for UNC, drive-path format, etc

    return true;
}
9
Micah

同じ問題に対する堅牢な解決策を探した後に見つけたいくつかの回答からまとめた解決策を投稿すると思いました。うまくいけば、それは他の誰かを助ける。

using System;
using System.IO;
//..

public static bool ValidateFilePath(string path, bool RequireDirectory, bool IncludeFileName, bool RequireFileName = false)
{
    if (string.IsNullOrEmpty(path)) { return false; }
    string root = null;
    string directory = null;
    string filename = null;
    try
    {
        // throw ArgumentException - The path parameter contains invalid characters, is empty, or contains only white spaces.
        root = Path.GetPathRoot(path);

        // throw ArgumentException - path contains one or more of the invalid characters defined in GetInvalidPathChars.
        // -or- String.Empty was passed to path.
        directory = Path.GetDirectoryName(path);

        // path contains one or more of the invalid characters defined in GetInvalidPathChars
        if (IncludeFileName) { filename = Path.GetFileName(path); }
    }
    catch (ArgumentException)
    {
        return false;
    }

    // null if path is null, or an empty string if path does not contain root directory information
    if (String.IsNullOrEmpty(root)) { return false; }

    // null if path denotes a root directory or is null. Returns String.Empty if path does not contain directory information
    if (String.IsNullOrEmpty(directory)) { return false; }

    if (RequireFileName)
    {
        // if the last character of path is a directory or volume separator character, this method returns String.Empty
        if (String.IsNullOrEmpty(filename)) { return false; }

        // check for illegal chars in filename
        if (filename.IndexOfAny(Path.GetInvalidFileNameChars()) >= 0) { return false; }
    }
    return true;
}
5
Enisle

ファイル名が有効であっても、touchを使用して、ユーザーに書き込み権限があることを確認できます。

短期間で何百ものファイルでディスクをスラッシングしないのであれば、空のファイルを作成するのが合理的なアプローチだと思います。

無効な文字をチェックするなど、もっと軽くしたい場合は、ファイル名をPath.GetInvalidFileNameChars()と比較します。

5
Michael Haren

考えられるすべての例外シナリオをカバーしようとするこの方法を試してください。ほとんどすべてのWindows関連のパスで機​​能します。

/// <summary>
/// Validate the Path. If path is relative append the path to the project directory by default.
/// </summary>
/// <param name="path">Path to validate</param>
/// <param name="RelativePath">Relative path</param>
/// <param name="Extension">If want to check for File Path</param>
/// <returns></returns>
private static bool ValidateDllPath(ref string path, string RelativePath = "", string Extension = "") {
    // Check if it contains any Invalid Characters.
    if (path.IndexOfAny(Path.GetInvalidPathChars()) == -1) {
        try {
            // If path is relative take %IGXLROOT% as the base directory
            if (!Path.IsPathRooted(path)) {
                if (string.IsNullOrEmpty(RelativePath)) {
                    // Exceptions handled by Path.GetFullPath
                    // ArgumentException path is a zero-length string, contains only white space, or contains one or more of the invalid characters defined in GetInvalidPathChars. -or- The system could not retrieve the absolute path.
                    // 
                    // SecurityException The caller does not have the required permissions.
                    // 
                    // ArgumentNullException path is null.
                    // 
                    // NotSupportedException path contains a colon (":") that is not part of a volume identifier (for example, "c:\"). 
                    // PathTooLongException The specified path, file name, or both exceed the system-defined maximum length. For example, on Windows-based platforms, paths must be less than 248 characters, and file names must be less than 260 characters.

                    // RelativePath is not passed so we would take the project path 
                    path = Path.GetFullPath(RelativePath);

                } else {
                    // Make sure the path is relative to the RelativePath and not our project directory
                    path = Path.Combine(RelativePath, path);
                }
            }

            // Exceptions from FileInfo Constructor:
            //   System.ArgumentNullException:
            //     fileName is null.
            //
            //   System.Security.SecurityException:
            //     The caller does not have the required permission.
            //
            //   System.ArgumentException:
            //     The file name is empty, contains only white spaces, or contains invalid characters.
            //
            //   System.IO.PathTooLongException:
            //     The specified path, file name, or both exceed the system-defined maximum
            //     length. For example, on Windows-based platforms, paths must be less than
            //     248 characters, and file names must be less than 260 characters.
            //
            //   System.NotSupportedException:
            //     fileName contains a colon (:) in the middle of the string.
            FileInfo fileInfo = new FileInfo(path);

            // Exceptions using FileInfo.Length:
            //   System.IO.IOException:
            //     System.IO.FileSystemInfo.Refresh() cannot update the state of the file or
            //     directory.
            //
            //   System.IO.FileNotFoundException:
            //     The file does not exist.-or- The Length property is called for a directory.
            bool throwEx = fileInfo.Length == -1;

            // Exceptions using FileInfo.IsReadOnly:
            //   System.UnauthorizedAccessException:
            //     Access to fileName is denied.
            //     The file described by the current System.IO.FileInfo object is read-only.-or-
            //     This operation is not supported on the current platform.-or- The caller does
            //     not have the required permission.
            throwEx = fileInfo.IsReadOnly;

            if (!string.IsNullOrEmpty(Extension)) {
                // Validate the Extension of the file.
                if (Path.GetExtension(path).Equals(Extension, StringComparison.InvariantCultureIgnoreCase)) {
                    // Trim the Library Path
                    path = path.Trim();
                    return true;
                } else {
                    return false;
                }
            } else {
                return true;

            }
        } catch (ArgumentNullException) {
            //   System.ArgumentNullException:
            //     fileName is null.
        } catch (System.Security.SecurityException) {
            //   System.Security.SecurityException:
            //     The caller does not have the required permission.
        } catch (ArgumentException) {
            //   System.ArgumentException:
            //     The file name is empty, contains only white spaces, or contains invalid characters.
        } catch (UnauthorizedAccessException) {
            //   System.UnauthorizedAccessException:
            //     Access to fileName is denied.
        } catch (PathTooLongException) {
            //   System.IO.PathTooLongException:
            //     The specified path, file name, or both exceed the system-defined maximum
            //     length. For example, on Windows-based platforms, paths must be less than
            //     248 characters, and file names must be less than 260 characters.
        } catch (NotSupportedException) {
            //   System.NotSupportedException:
            //     fileName contains a colon (:) in the middle of the string.
        } catch (FileNotFoundException) {
            // System.FileNotFoundException
            //  The exception that is thrown when an attempt to access a file that does not
            //  exist on disk fails.
        } catch (IOException) {
            //   System.IO.IOException:
            //     An I/O error occurred while opening the file.
        } catch (Exception) {
            // Unknown Exception. Might be due to wrong case or nulll checks.
        }
    } else {
        // Path contains invalid characters
    }
    return false;
}
2
vCillusion

静的 GetInvalidFileNameCharsメソッドPathクラスSystem.IO名前空間 を使用して、どの文字を決定するかファイル名に違法です。

パスでこれを行うには、同じクラスでstatic GetInvalidPathChars method を呼び出します。

パスのルートが有効かどうかを判断するには、GetPathRootクラスでstatic Path method を呼び出してルートを取得し、次に Directory class 有効かどうかを判断します。その後、残りのパスを通常どおり検証できます。

2
casperOne

パスまたはファイル名が無効な場合、いくつかのSystem.IO.Pathメソッドは例外をスローします。

  • Path.IsPathRooted()
  • Path.GetFileName()

http://msdn.Microsoft.com/en-us/library/system.io.path_methods.aspx

2
shackett

他の人が示したように、正規表現を使用して運が良かった。

覚えておくべきことの1つは、Windowsでは少なくとも合法的な文字を含む一部のファイル名を禁止していることです。いくつかが思い浮かびます:com、nul、prn。

今は持っていませんが、これらのファイル名を考慮に入れた正規表現があります。あなたが望むなら、私はそれを投稿することができます、さもなければ私はあなたが私と同じ方法でそれを見つけることができると確信しています:Google。

-ジェイ

1
Jay Riggs

私はあなたのためにそれをすべて検証することができる、すぐに使えるものは知りませんが、.NETPathクラスはあなたを大いに助けることができます。

まず第一に、それは:

char[] invalidChars = Path.GetInvalidFileNameChars(); //returns invalid charachters

または:

Path.GetPathRoot(string); // will return the root.
1
BFree

これにより、マシン上のドライブが取得されます。

System.IO.DriveInfo.GetDrives()

これらの2つの方法により、チェックする不良文字を取得できます。

System.IO.Path.GetInvalidFileNameChars();
System.IO.Path.GetInvalidPathChars();
0
Austin Salonen

答えるのは遅すぎると思いますが... :)ボリューム名のあるパスの場合、次のように書くことができます:

using System;
using System.Linq;
using System.IO;

// ...

var drives = Environment.GetLogicalDrives();
var invalidChars = Regex.Replace(new string(Path.GetInvalidFileNameChars()), "[\\\\/]", "");
var drive = drives.FirstOrDefault(d => filePath.StartsWith(d));
if (drive != null) {
    var fileDirPath = filePath.Substring(drive.Length);
    if (0 < fileDirPath.Length) {
        if (fileDirPath.IndexOfAny(invalidChars.ToCharArray()) == -1) {
            if (Path.Combine(drive, fileDirPath) != drive) {
                // path correct and we can proceed
            }
        }
    }
}
0
QgecNick

おそらく最良の方法は、ファイルシステムで正規表現と小さなルックアップの組み合わせを組み合わせたカスタムメソッドを構築することです(たとえば、ドライブを表示するため)

0
tanathos