2009-01-26 18 views
21

C# 'da bir statik üye işlevi yazmaya çalışıyorum ya da dosya sisteminin belirttiği dosya yolunu yeniden içerecek olan .NET Framework'te bir tane bulmaya çalışıyorum.C# Filepath Recasing

Örnek:

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 

aşağıda Aşağıdaki kodu ve bunun pek çok çeşidi denedim ve hala çalışmıyor. Windows'un genelde büyük/küçük harf duyarlı olduğunu biliyorum, ancak bu dosya yollarını bir Unix ve Windows uygulaması olduğu için dosya yolu kasalarını dikkate alan ClearCase'e aktarmam gerekiyor. Sen davayı almak ve arama sonuçları döndürmek istediğiniz dosyanın arayabilirsiniz

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; 
} 
+0

. Ben zaten bu konuda söyledim. –

cevap

21

Bu dosya ve dizinleri hiç var ve erişilebilir olduğunu varsayar oldukça basit bir uygulamasıdır. Yukarıdaki orijinal kodunuz aynısını yaptı, bu yüzden bu davranışı istediğinizi varsayıyorum.

1) Tüm durumlar için çalışmak görünmüyor:

+0

Bu maalesef UNC yollarını kırıyor. UNC yollarında çalışmak için ona ihtiyacım var. \\ SERVERNAME \ Hostdir \ MyDocument.docx –

+0

gibi Ben bunu cevap olarak koyacağım. İhtiyaçlarım için en iyisini çalışır. Çalışmasını sağlamak için bu hack'in üstüne ek hack ekleyebilirim ama sonuçta ortaya çıkan komplikasyonlardan dolayı çıkıyorum. –

+2

Ben 'dirInfo.Name' un UNC hisseleri için yanlış olduğunu buldum, çünkü sunucu adını düşürüyor. Benim amaçlarım için, 'dirInfo.FullName.ToUpperInvariant()' yeterince iyidir - paylaşım adı için doğru durumu kurtarmaz, ancak geçerli bir yol oluşturur. – Weeble

1

(sağ, var olan bir dosyanın kasasını kontrol edeyim?). Buna benzer bir şey:

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

Bu sizin için mi arıyorsunuz? Bu bir hata var

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); 
} 

olsa: göreli yollar mutlak yollara dönüştürülür

+0

Durum yalnızca dosya mevcutsa orada olacaktır. Aksi halde önemli değil mi? – manojlds

+0

Bu, dosyanın durumunu düzeltir, ancak yolun geri kalanı tümüyle hatalı şekilde korunur. – PolyTekPatrick

1

Ben daha verimli bir şey ama var. (Hangi dosya ve dizinlerin doğru şekilde kasa aldığını ve hangilerinin doğru olmadığını anlayamadım.)

2) Windows'a özgüdür.

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); 
3

Aşağıdakiler, test ettiğim kadar iyi çalışıyor ... yalnızca, kullanılan API'nın yalnızca Vista'da mevcut olması yakalamadır.

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); 
+1

Vista için güzel bir çözüm. Bunun sembolik bağları çözdüğünü unutmayın. Şu adresteki yorumlara bakın: http://msdn.microsoft.com/en-us/library/aa364962(VS.85).aspx – Ants

1

yukarıda @Ants tarafından cevap kesinlikle kabul edilen yanıt olarak kredi almak gerekir. Ancak, bunu benim amacım için biraz değiştirdim. Yaklaşım FileInfo ve DirectoryInfo için uzatma yöntemleri olarak paketlenmiştir ve düzeltilmiş olanları da iade etmektedir.

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 ile bazı büyüklük-tutarsızlık sorunları üzerinde başımı çarptım. Sağlamlığı sağlamak için, yolların karşılaştırması veya saklanması sırasında tüm büyük harflere dönüyorum. kodların amaçlarını netleştirmek için, ben de bu uzatma yöntemleri vardır: sistem sizin için dosyayı bulmak isteyeceksiniz

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

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

.

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

yüzden tam dosya adını filtreleme ve geçerli dizine arama sınırlayarak, dizinde arama: Ben, yani tam yolunu biliyor sistemi arama olmadığını davranarak bunu sadece (tekrarlama yok).

Bu, tek bir dosya yolunu doğru kasayla (dosya varsa) veya hiçbir şey (dosya yoksa) içeren bir dize dizisi döndürür.

Bir uyarı: Joker karakterleri giriş yoluna izin vermeyebilirsiniz, çünkü bu yaklaşım bunları kabul eder ve sonuç olarak birden fazla dosya bulabilir.

Düzenleme

sürücü harfi hala sağladığımız kılıfı izleyin görünmektedir. Ayrıca, bu UNC yolları için test edilmesi gerekiyor. ClearCase'den dolayı