2009-01-26 7 views
21

Estoy tratando de escribir una función miembro estática en C# o encontrar una en .NET Framework que volverá a mayúsculas una ruta de archivo a lo que especifica el sistema de archivos.C# Filepath Recasing

Ejemplo:

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 

he intentado el siguiente código de abajo y muchas variantes de la misma y todavía no funciona. Sé que Windows no distingue entre mayúsculas y minúsculas en general, pero necesito pasar estas rutas de acceso de archivos a ClearCase, que considera el alojamiento de la ruta de archivos, ya que es una aplicación de Unix y 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; 
} 
+0

Debido a ClearCase. Ya lo dije en la pregunta. –

Respuesta

21

Esta es una aplicación muy simple que asume que el archivo y todos los directorios existen y son accesibles:

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

Hay un error con esto, sin embargo: Las rutas relativas se convierten en rutas absolutas. Tu código original anterior hizo lo mismo, así que supongo que quieres este comportamiento.

+0

Esto se rompe en las rutas UNC desafortunadamente. Necesito que trabaje en las rutas UNC. Como \\ SERVERNAME \ Hostdir \ MyDocument.docx –

+0

Voy a poner esto como la respuesta. Para mis necesidades, funciona mejor. Puedo agregar ataques adicionales a este ataque para que funcione, pero resulta que estoy dejando la función debido a complicaciones. –

+2

Descubrí que 'dirInfo.Name' era simplemente incorrecto para los recursos compartidos de UNC, ya que elimina el nombre del servidor. Para mis propósitos, 'dirInfo.FullName.ToUpperInvariant()' es lo suficientemente bueno - no recupera el caso correcto para el nombre compartido, pero sí construye una ruta válida. – Weeble

1

Puede buscar el archivo que desea obtener el caso de y devolver los resultados de su búsqueda (que quiere comprobar la carcasa de un archivo que existe, ¿verdad?). Algo como esto:

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

¿Esto es lo que estás buscando?

+0

El caso estará allí solo si el archivo existe. De lo contrario, no importa, ¿no crees? – manojlds

+0

Esto arregla la caja del archivo, pero todo el resto de la ruta permanece incorrectamente encajonada. – PolyTekPatrick

1

que tienen algo más eficiente, pero:

1) No parece que trabajar para todos los casos. (No he descubierto el patrón de qué archivos y directorios recibe correctamente la carcasa, y cuáles no).

2) Es específico de Windows.

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

Lo que sigue funciona bien en la medida en que lo probé ... lo único sorprendente es que la API utilizada está disponible solo en Vista.

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

Buena solución para Vista. Ten en cuenta que esto resuelve los enlaces simbólicos. Consulte los comentarios en: http://msdn.microsoft.com/en-us/library/aa364962(VS.85).aspx – Ants

1

La respuesta por encima @Ants debe absolutamente obtener crédito como la respuesta aceptada. Sin embargo, lo modifiqué un poco para mis propósitos. El enfoque está empaquetado como métodos de extensión para FileInfo y DirectoryInfo, y también devuelve los corregidos.

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

He estado golpeando mi cabeza sobre algunos problemas de inconsistencia de casos con FileInfo. Para garantizar la solidez, paso a mayúsculas cuando comparo o almaceno las rutas. Para aclarar la intención del código, también tengo estos métodos de extensión:

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

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

Usted querrá el sistema para encontrar el archivo para usted. Lo hago por pretender que no sé la ruta exacta, es decir, que el sistema búsqueda:

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

Así que la búsqueda en el directorio, filtrando en el nombre exacto del archivo y limitar la búsqueda en el directorio actual solo (sin recursividad).

Esto devuelve una matriz de cadenas que contiene la ruta del archivo único con la carcasa correcta (si el archivo existe) o nada (si el archivo no existe).

Una advertencia: es posible que deba deshabilitar los comodines en la ruta de entrada, porque este enfoque los acepta y puede encontrar varios archivos como resultado.

Editar

La letra de la unidad parece seguir siendo la carcasa que proporcionamos. Además, esto debe probarse para rutas UNC.

Cuestiones relacionadas