Pregunta

Estoy intentando escribir una función miembro estática en C # o encontrar una en .NET Framework que vuelva a colocar una ruta de archivo a lo que especifica el sistema de archivos.

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 a continuación y muchas variantes de él y todavía no funciona. Sé que Windows no distingue entre mayúsculas y minúsculas en general, pero necesito pasar estas rutas de archivo a ClearCase, que considera la carcasa de la ruta de archivo, 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;
}
¿Fue útil?

Solución

Esta es una implementación bastante simple que asume que todos los archivos y 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);
}

Sin embargo, hay un error con esto: las rutas relativas se convierten en rutas absolutas. Su código original anterior hizo lo mismo, por lo que supongo que desea este comportamiento.

Otros consejos

Lo siguiente funciona bien en la medida en que lo probé ... el único inconveniente 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);

Puede buscar el archivo en el que desea obtener el caso y devolver los resultados de su búsqueda (desea verificar 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];
}

¿Es esto lo que estás buscando?

Tengo algo más eficiente pero:

1) No parece funcionar para todos los casos. (No he descubierto el patrón de qué archivos y directorios obtiene 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);

La respuesta de @Ants anterior debería absolutamente obtener crédito como la respuesta aceptada. Sin embargo, lo refactoré 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 mayúsculas y minúsculas con FileInfo. Para garantizar la robustez, convierto a todas las mayúsculas al hacer la comparación o el almacenamiento de 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();
}

Querrá que el sistema encuentre el archivo por usted. Hago esto fingiendo que no conozco la ruta exacta, es decir, tengo el sistema search :

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

Por lo tanto, buscamos en el directorio, filtramos el nombre exacto del archivo y limitamos la búsqueda solo al directorio actual (sin recurrencia).

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 como resultado puede encontrar varios archivos.

Editar

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

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top