سؤال

أحاول كتابة وظيفة عضو ثابت في C# أو العثور على واحدة في .NET Framework والتي ستعيد حالة مسار الملف إلى ما يحدده نظام الملفات.

مثال:

string filepath = @"C:\temp.txt";
filepath = FileUtility.RecaseFilepath(filepath);

// filepath = C:\Temp.TXT
// Where the real fully qualified filepath in the NTFS volume is C:\Temp.TXT

لقد جربت الكود التالي أدناه والعديد من المتغيرات منه وما زال لا يعمل.أعلم أن Windows غير حساس لحالة الأحرف بشكل عام ولكني بحاجة إلى تمرير مسارات الملفات هذه إلى ClearCase الذي يأخذ في الاعتبار غلاف مسار الملف نظرًا لأنه تطبيق Unix وWindows.

public static string GetProperFilePathCapitalization(string filepath)
{
    string result = "";

    try
    {
        result = Path.GetFullPath(filepath);
        DirectoryInfo dir = new DirectoryInfo(Path.GetDirectoryName(result));
        FileInfo[] fi = dir.GetFiles(Path.GetFileName(result));
        if (fi.Length > 0)
        {
            result = fi[0].FullName;
        }
    }
    catch (Exception)
    {
        result = filepath;
    }

    return result;
}
هل كانت مفيدة؟

المحلول

وهذا هو تطبيق بسيط جدا التي يفترض أن الملفات والدلائل عن وجود ويمكن الوصول إليها:

static string GetProperDirectoryCapitalization(DirectoryInfo dirInfo)
{
    DirectoryInfo parentDirInfo = dirInfo.Parent;
    if (null == parentDirInfo)
        return dirInfo.Name;
    return Path.Combine(GetProperDirectoryCapitalization(parentDirInfo),
                        parentDirInfo.GetDirectories(dirInfo.Name)[0].Name);
}

static string GetProperFilePathCapitalization(string filename)
{
    FileInfo fileInfo = new FileInfo(filename);
    DirectoryInfo dirInfo = fileInfo.Directory;
    return Path.Combine(GetProperDirectoryCapitalization(dirInfo),
                        dirInfo.GetFiles(fileInfo.Name)[0].Name);
}

وهناك خلل مع هذا، على الرغم من: يتم تحويل مسارات النسبية لمسارات مطلقة. كود الأصلي فوق فعل الشيء نفسه، لذلك أفترض أنك لا تريد هذا السلوك.

نصائح أخرى

وويعمل تحت يرام إلى حد اختبرت ... الصيد فقط هو أن API المستخدم هو متوفر فقط في ويندوز فيستا.

static void Main(string[] args)
{
    using (FileStream fs = File.OpenRead(@"D:\temp\case\mytest.txt"))
    {
        StringBuilder path = new StringBuilder(512);
        GetFinalPathNameByHandle(fs.SafeFileHandle.DangerousGetHandle(), path, path.Capacity, 0);
        Console.WriteLine(path.ToString());
    }
}

[DllImport("kernel32.dll", SetLastError = true)]
static extern int GetFinalPathNameByHandle(IntPtr handle, [In, Out] StringBuilder path, int bufLen, int flags);

ويمكنك البحث عن الملف الذي ترغب في الحصول على هذه القضية يوم والعودة نتائج البحث (كنت تريد التحقق من غلاف من ملف موجود، أليس كذلك؟). شيء من هذا القبيل:

public static string GetProperFilePathCapitalization(string filepath) {
   string directoryPath = Path.GetDirectoryName(filepath);
   string[] files = Directory.GetFiles(directoryPath, Path.GetFileName(filepath));
   return files[0];
}

وهذا هو ما كنت تبحث عنه؟

ولدي شيء أكثر كفاءة ولكن:

1) لا يبدو للعمل لجميع الحالات. (أنا لم ترد على نمط الملفات والدلائل فإنه يحصل على غلاف بشكل صحيح، وتلك التي لا.)

2) انها ويندوز محددة.

static string GetProperFilePathCapitalization1(string filename)
{
    StringBuilder sb = new StringBuilder(260);
    int length = GetLongPathName(filename, sb, sb.Capacity);

    if (length > sb.Capacity)
    {
        sb.Capacity = length;
        length = GetLongPathName(filename, sb, sb.Capacity);
    }

    if (0 == length)
        throw new Win32Exception("GetLongPathName");

    return sb.ToString();
}

[DllImport("kernel32.dll")]
static extern int GetLongPathName(string path, StringBuilder pszPath, int cchPath);

والجواب من قبلAnts أعلاه ينبغي أن <م> تماما الحصول على الائتمان، والجواب المقبول. ومع ذلك، وأنا ريفاكتوريد عليه قليلا لأغراض بلدي. يتم حزم النهج وسائل التمديد لFileInfo وDirectoryInfo، وعودة تصحيح منها كذلك.

public static DirectoryInfo GetProperCasedDirectoryInfo(this DirectoryInfo dirInfo)
{
    // Inspired by http://stackoverflow.com/a/479198/244342

    if (!dirInfo.Exists)
    {
        // Will not be able to match filesystem
        return dirInfo;
    }

    DirectoryInfo parentDirInfo = dirInfo.Parent;
    if (parentDirInfo == null)
    {
        return dirInfo;
    }
    else
    {
        return parentDirInfo.GetProperCasedDirectoryInfo().GetDirectories(dirInfo.Name)[0];
    }
}

public static FileInfo GetProperCasedFileInfo(this FileInfo fileInfo)
{
    // Inspired by http://stackoverflow.com/a/479198/244342

    if (!fileInfo.Exists)
    {
        // Will not be able to match filesystem
        return fileInfo;
    }

    return fileInfo.Directory.GetProperCasedDirectoryInfo().GetFiles(fileInfo.Name)[0];
}

ولقد تم ضجيجا رأسي على بعض القضايا حالة تناقض مع FileInfo. من أجل ضمان متانة، وتحويل لجميع القبعات عند القيام المقارنة أو تخزين المسارات. لتوضيح القصد من القانون، ولدي أيضا هذه الأساليب التمديد:

public static string GetPathForKey(this FileInfo File)
{
    return File.FullName.ToUpperInvariant();
}

public static string GetDirectoryForKey(this FileInfo File)
{
    return File.DirectoryName.ToUpperInvariant();
}

ستحتاج إلى أن يعثر النظام على الملف نيابةً عنك.أفعل ذلك من خلال التظاهر بأنني لا أعرف المسار الدقيق، أي.لديك النظام يبحث:

var fileName = Path.GetFileName(filePath);
var dir = Path.GetDirectoryName(filePath);
var filePaths = Directory.GetFiles(dir, fileName, SearchOption.TopDirectoryOnly);
var caseCorrectedFilePath = filePaths.FirstOrDefault();

لذلك نقوم بالبحث في الدليل، والتصفية حسب اسم الملف الدقيق وقصر البحث على الدليل الحالي فقط (بدون تكرار).

يؤدي هذا إلى إرجاع مصفوفة سلسلة تحتوي إما على مسار ملف واحد مع الغلاف الصحيح (إذا كان الملف موجودًا) أو لا شيء (إذا كان الملف غير موجود).

تحذير واحد:قد تحتاج إلى عدم السماح بأحرف البدل في مسار الإدخال، لأن هذا الأسلوب يقبلها وقد يعثر على ملفات متعددة نتيجة لذلك.

يحرر

يبدو أن حرف محرك الأقراص لا يزال يتبع الغلاف الذي نقدمه.أيضاً، هذا يحتاج إلى اختبار لمسارات UNC.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top