18

大文字と小文字を区別する方法はありますかDirectory.Exists/File.Exists以降

Directory.Exists(folderPath)

Directory.Exists(folderPath.ToLower())

両方とも戻りtrueますか?

ほとんどの場合、それは問題ではありませんが、パスがケースと 100% 一致しないと機能しないように見えるマクロを使用しています。

4

6 に答える 6

5

Directory.Exists は大文字と小文字を区別しないFindFirstFileを使用するため、いいえ。ただし、追加のフラグパラメーターをFIND_FIRST_EX_CASE_SENSITIVEに設定して、 FindFirstFileEx を PInvokeすることはできます。

于 2013-04-24T05:18:13.583 に答える
2

この機能を試してください:

public static bool FileExistsCaseSensitive(string filename)
{
    string name = Path.GetDirectoryName(filename);

    return name != null 
           && Array.Exists(Directory.GetFiles(name), s => s == Path.GetFullPath(filename));
}

アップデート:

コメントで述べたように、これはパスではなくファイル名のケースのみをチェックします。これは、GetFullPath メソッドが Windows の元のパスを元のケースで返すのではなく、パラメーターからのパスのコピーを返すためです。

元:

GetFullPath("c:\TEST\file.txt") -> "c:\TEST\file.txt"
GetFullPath("c:\test\file.txt") -> "c:\test\file.txt"

私が試したすべての方法は同じように機能します:Fileinfo、DirectoryInfo。

kernel32.dll メソッドを使用したソリューションを次に示します。

    [DllImport("kernel32.dll", CharSet = CharSet.Auto)]
    public static extern int GetLongPathName(
        string path,
        StringBuilder longPath,
        int longPathLength
        );

    /// <summary>
    /// Return true if file exists. Non case sensitive by default.
    /// </summary>
    /// <param name="filename"></param>
    /// <param name="caseSensitive"></param>
    /// <returns></returns>
    public static bool FileExists(string filename, bool caseSensitive = false)
    {
        if (!File.Exists(filename))
        {
            return false;
        }

        if (!caseSensitive)
        {
            return true;
        }

        //check case
        StringBuilder longPath = new StringBuilder(255);
        GetLongPathName(Path.GetFullPath(filename), longPath, longPath.Capacity);

        string realPath = Path.GetDirectoryName(longPath.ToString());
        return Array.Exists(Directory.GetFiles(realPath), s => s == filename);
    }
于 2013-05-27T14:27:17.513 に答える
1

この質問の解決策に基づいて、Windows ドライブ文字を除くパス全体で大文字と小文字を区別する以下のコードを作成しました。

 static void Main(string[] args)
    {
        string file1 = @"D:\tESt\Test.txt";
        string file2 = @"d:\Test\test.txt";
        string file3 = @"d:\test\notexists.txt";

        bool exists1 = Case_Sensitive_File_Exists(file1);
        bool exists2 = Case_Sensitive_File_Exists(file2);
        bool exists3 = Case_Sensitive_File_Exists(file3);

        Console.WriteLine("\n\nPress any key...");
        Console.ReadKey();
    }

   static bool Case_Sensitive_File_Exists(string filepath)
   {
        string physicalPath = GetWindowsPhysicalPath(filepath);
        if (physicalPath == null) return false;
        if (filepath != physicalPath) return false;
        else return true;
   }

質問GetWindowsPhysicalPath(string path)からのコードをコピーしました

  [DllImport("kernel32.dll", SetLastError = true, CharSet = CharSet.Auto)]
    static extern uint GetLongPathName(string ShortPath, StringBuilder sb, int buffer);

    [DllImport("kernel32.dll")]
    static extern uint GetShortPathName(string longpath, StringBuilder sb, int buffer);

    protected static string GetWindowsPhysicalPath(string path)
    {
        StringBuilder builder = new StringBuilder(255);

        // names with long extension can cause the short name to be actually larger than
        // the long name.
        GetShortPathName(path, builder, builder.Capacity);

        path = builder.ToString();

        uint result = GetLongPathName(path, builder, builder.Capacity);

        if (result > 0 && result < builder.Capacity)
        {
            //Success retrieved long file name
            builder[0] = char.ToLower(builder[0]);
            return builder.ToString(0, (int)result);
        }

        if (result > 0)
        {
            //Need more capacity in the buffer
            //specified in the result variable
            builder = new StringBuilder((int)result);
            result = GetLongPathName(path, builder, builder.Capacity);
            builder[0] = char.ToLower(builder[0]);
            return builder.ToString(0, (int)result);
        }

        return null;
    }

この関数で私が見つけた唯一の問題は、ドライブ文字が常に小文字のように見えることです。例: Windows の物理パスは次のとおりです。D:\Test\test.txt関数は次をGetWindowsPhysicalPath(string path)返します。d:\Test\test.txt

于 2015-10-07T15:09:46.710 に答える
0

PInvoke を使用する必要がなく、null 許容ブール値 (bool?) を返すこれらの 2 つの単純なオプションを試してください。私はその分野の専門家ではないので、これが最も効率的なコードかどうかはわかりますが、私にとってはうまくいきます。

単純にパスを渡し、結果が null (HasValue = false) の場合は一致が見つかりません。結果が false の場合は完全一致、それ以外の場合は true の場合は大文字と小文字が異なる一致があります。

メソッド GetFiles、GetDirectories、および GetDrives はすべて、ファイル システムに保存されている正確な大文字と小文字を返すため、大文字と小文字を区別する比較メソッドを使用できます。

注意: パスが正確なドライブ (@"C:\" など) の場合は、少し異なるアプローチを使用する必要があります。

using System.IO;
class MyFolderFileHelper {
    public static bool? FileExistsWithDifferentCase(string fileName)
    {
        bool? result = null;
        if (File.Exists(fileName))
        {
            result = false;
            string directory = Path.GetDirectoryName(fileName);
            string fileTitle = Path.GetFileName(fileName);
            string[] files = Directory.GetFiles(directory, fileTitle);
            if (String.Compare(files[0], fileName, false) != 0)
                result = true;                
        }
        return result;
    }

    public static bool? DirectoryExistsWithDifferentCase(string directoryName)
    {
        bool? result = null;
        if (Directory.Exists(directoryName))
        {
            result = false;
            directoryName = directoryName.TrimEnd(Path.DirectorySeparatorChar);

            int lastPathSeparatorIndex = directoryName.LastIndexOf(Path.DirectorySeparatorChar);
            if (lastPathSeparatorIndex >= 0)
            {                       
                string baseDirectory = directoryName.Substring(lastPathSeparatorIndex + 1);
                string parentDirectory = directoryName.Substring(0, lastPathSeparatorIndex);

                string[] directories = Directory.GetDirectories(parentDirectory, baseDirectory);
                if (String.Compare(directories[0], directoryName, false) != 0)
                    result = true;
            }
            else
            {
                //if directory is a drive
                directoryName += Path.DirectorySeparatorChar.ToString();
                DriveInfo[] drives = DriveInfo.GetDrives();
                foreach(DriveInfo driveInfo in drives)
                {
                    if (String.Compare(driveInfo.Name, directoryName, true) == 0)
                    {
                        if (String.Compare(driveInfo.Name, directoryName, false) != 0)
                            result = true;
                        break;
                    }
                }

            }
        }
        return result;
    }
}
于 2015-06-19T00:11:41.693 に答える