2012-01-28 17 views
17

Por ejemplo, ¿cómo puedo hacer esto¿Cómo hacer una ruta absoluta relativa a una carpeta en particular?

"C:\RootFolder\SubFolder\MoreSubFolder\LastFolder\SomeFile.txt" 

relativa a esta carpeta

"C:\RootFolder\SubFolder\" 

si el resultado esperado es

"MoreSubFolder\LastFolder\SomeFile.txt" 
+0

¿No sería el resultado esperado "MoreSubFolder \ LastFolder \ SomeFile.txt"? –

+0

¡Sí, gracias por señalar mi error! – asmo

+0

Debe reformular esto. Lo leí dos veces, y todavía no estoy seguro de lo que realmente quieres.De lo contrario, estoy tentado de responder: use los métodos IndexOf y Substring para obtener la segunda parte de la ruta (o para eliminar la primera parte de la ruta), y tengo la sensación de que no es lo que quiere. Mire en los métodos estáticos de la clase System.IO.Path: tiene algunos buenos ayudantes para combinar rutas y similares. –

Respuesta

28

Sí, se puede hacer eso , es fácil, pensar en sus rutas como URI:

Uri fullPath = new Uri(@"C:\RootFolder\SubFolder\MoreSubFolder\LastFolder\SomeFile.txt", UriKind.Absolute); 
Uri relRoot = new Uri(@"C:\RootFolder\SubFolder\", UriKind.Absolute); 

string relPath = relRoot.MakeRelativeUri(fullPath).ToString(); 
// relPath == @"MoreSubFolder\LastFolder\SomeFile.txt" 
+4

No funciona con espacios: https://ideone.com/cLe7wf –

+3

'relPath = Uri.UnescapeDataString (relPath)' para corregir espacios. –

+0

Si la ruta raíz no termina con "\", entonces la última parte de la ruta raíz no se eliminará de la ruta completa. –

11

En su ejemplo, es simplemente absPath.Substring(relativeTo.Length).

ejemplo más elaborado requeriría que se remonta unos niveles de la relativeTo, de la siguiente manera:

"C:\RootFolder\SubFolder\MoreSubFolder\LastFolder\SomeFile.txt" 
"C:\RootFolder\SubFolder\Sibling\Child\" 

El algoritmo para hacer una ruta relativa se vería de la siguiente manera:

  • Retire la más larga común prefijo (en este caso, es "C:\RootFolder\SubFolder\")
  • Cuenta el número de carpetas en relativeTo (en este caso, es 2: "Sibling\Child\")
  • Insertar ..\ para cada carpeta restante
  • Concatenate con el resto de la ruta absoluta después de la eliminación sufijo

El resultado final es el siguiente:

"..\..\MoreSubFolder\LastFolder\SomeFile.txt" 
+1

O "eliminar el prefijo común más largo que termina en una barra inclinada". –

-2

¿Por qué todas esas soluciones complicadas?
¿Y en relación con Uri? De Verdad ? No tendrá que esperar mucho para la primera excepción.
Brilla en simplicidad.
No hay necesidad de ninguna clase de marco adicional.

public static string BuildRelativePath(string absolutePath, string basePath) 
    { 
     return absolutePath.Substring(basePath.Length); 
    } 

Y en caso de que no se puede administrar para agregar siempre o siempre omitir la System.IO.Path.DirectorySeparatorChar de cierre de las cuerdas, o no es capaz de no mezclar los argumentos:

public static string FaultTolerantRelativePath(string absolutePath, string basePath) 
{ 
    if(absolutePath == null || basePath == null) 
     return null; 

    absolutePath = absolutePath.Replace(System.IO.Path.DirectorySeparatorChar, '/'); 
    basePath = basePath.Replace(System.IO.Path.DirectorySeparatorChar, '/'); 

    if (!basePath.EndsWith("/")) 
     basePath += "/"; 

    if (!absolutePath.EndsWith("/")) 
     absolutePath += "/"; 

    if (absolutePath.Length < basePath.Length) 
     throw new ArgumentException("absolutePath.Length < basePath.Length ? This can't be. You mixed up absolute and base path."); 

    string resultingPath = absolutePath.Substring(basePath.Length); 
    resultingPath = resultingPath.Replace('/', System.IO.Path.DirectorySeparatorChar); 

    return resultingPath; 
} 
+2

Estoy de acuerdo con el autor: ¿por qué soluciones complejas que involucran la clase Uri? Exceso de bits. Pero esta solución no funcionará bien en todos los casos; es necesario que haya una mejor solución que esta. – TarmoPikaro

1

Aquí están mis 5 centavos sin utilizar ninguna clase Url especial para ese propósito.

Buscar en makeRelative siguiente repositorio SVN:

https://sourceforge.net/p/syncproj/code/HEAD/tree/syncProj.cs#l976

que va a corregir los errores si hay alguna.

+0

Lo sentimos, pero parece que esto no funciona 'makeRelative (@" F: \ a \ b ", @" F: \ ")' por ejemplo devuelve '.. \ b' (en lugar de' a \ b') – Mikescher

+0

¿Puedes volver a intentarlo? ¿He actualizado mi última versión? Si no funciona, lo arreglaré. – TarmoPikaro

+0

Sí, parece correcto ahora. Aclamaciones. – Mikescher

Cuestiones relacionadas