java - txt - Convertir rutas relativas en rutas absolutas
rutas relativas html (9)
Tengo una ruta absoluta al archivo A.
Tengo una ruta relativa al archivo B del directorio A del archivo. Esta ruta puede y usará ".." para subir la estructura del directorio en formas arbitrariamente complejas.
Ejemplo A:
C:/projects/project1/module7/submodule5/fileA
Ejemplo Bs:
-
../../module3/submodule9/subsubmodule32/fileB
-
../submodule5/fileB
-
../../module7/../module4/submodule1/fileB
-
fileB
¿Cómo combino los dos para obtener la ruta absoluta más simple posible al archivo B?
A partir de su pregunta, si pudiera hacerlo bien, está buscando obtener una ruta de acceso relativa de la ruta relativa, luego puede hacer lo siguiente.
File b = new File("../some/relative/path");
String absolute = b.getCanonicalPath(); // may throw IOException
o notación abreviada puede ser,
String absolute = new File("../some/relative/path").getCanonicalPath();
Aquí está el código de ejemplo que funciona para mí.
public String absolutePath(String relative, String absoluteTo)
{
String[] absoluteDirectories = relative.split("////");
String[] relativeDirectories = absoluteTo.split("////");
int relativeLength = relativeDirectories.length;
int absoluteLength = absoluteDirectories.length;
int lastCommonRoot = 0;
int index;
for (index = 0; index < relativeLength; index++)
if (relativeDirectories[index].equals("..////"))
lastCommonRoot = index;
else
break;
StringBuilder absolutePath = new StringBuilder();
for (index = 0; index < absoluteLength - lastCommonRoot; index++)
{
if (absoluteDirectories[index].length() > 0)
absolutePath.append(absoluteDirectories[index] + "////");
}
for (index = lastCommonRoot; index < relativeLength - lastCommonRoot;
index++)
{
if (relativeDirectories[index].length() > 0)
absolutePath.append(relativeDirectories[index] + "////");
}
return absolutePath.toString();
}
También me la conversión a relativa:
public String relativePath(String absolute, String relativeTo) throws Exception
{
String[] absoluteDirectories = absolute.split("////");
String[] relativeDirectories = relativeTo.split("////");
int length = absoluteDirectories.length < relativeDirectories.length ?
absoluteDirectories.length : relativeDirectories.length;
int lastCommonRoot = -1;
int index;
for (index = 0; index < length; index++)
if (absoluteDirectories[index].equals(relativeDirectories[index]))
lastCommonRoot = index;
else
break;
if (lastCommonRoot > -1){
StringBuilder relativePath = new StringBuilder();
for (index = lastCommonRoot + 1; index <absoluteDirectories.length;
index++)
if (absoluteDirectories[index].length() > 0)
relativePath.append("..////");
for (index = lastCommonRoot + 1; index <relativeDirectories.length-1;
index++)
relativePath.append(relativeDirectories[index] + "////");
relativePath.append(relativeDirectories[relativeDirectories.length - 1]);
return relativePath.toString();
}
else{
throw new Exception("No common root found between working direcotry and filename");
}
}
En Java 7 también puedes usar la interfaz de Path :
Path basePath = FileSystems.getDefault().getPath("C://projects//project1//module7//submodule5//fileA");
Path resolvedPath = basePath.getParent().resolve("..//..//module3//submodule9//subsubmodule32//fileB"); // use getParent() if basePath is a file (not a directory)
Path abolutePath = resolvedPath.normalize();
Lo que es mejor que simplemente crear una utilidad que convierte las rutas relativas en rutas absolutas es crear una utilidad que convierta cualquier ruta que se le pase a una ruta absoluta para que no tenga que verificar el lado del cliente.
El código siguiente funciona para mí en ambos casos y he usado el tipo de String
en la firma del método (tanto el parámetro como el valor de retorno):
public static String toAbsolutePath(String maybeRelative) {
Path path = Paths.get(maybeRelative);
Path effectivePath = path;
if (!path.isAbsolute()) {
Path base = Paths.get("");
effectivePath = base.resolve(path).toAbsolutePath();
}
return effectivePath.normalize().toString();
}
Cambiar el código anterior para exponer los tipos de Path
en la firma del método es trivial (y, en realidad, más sencillo), pero creo que el uso de String
en la firma proporciona más flexibilidad.
Pruebe FilenameUtils.normalize()
de Apache commons-io
Ruta de Windows a la ruta completa de Java.
String winPath = downloadPath+"//"+dir_contents[i].getName();
String absPath = winPath.replace("//","////");
Sé que no es la mejor solución, pero no puede simplemente combinar la subcadena de la ruta del archivo A desde 0 hasta el lastIndexOf("/")
con la ruta del archivoB.
Ejemplo A:
-
C:/projects/project1/module7/submodule5/fileA
Ejemplo Bs:
-
../../module3/submodule9/subsubmodule32/fileB
C:/projects/project1/module7/submodule5/../../module3/submodule9/subsubmodule32/fileB
Si no desea el ..
allí, entonces, tomaría más tiempo, pero le recomiendo que vaya por la ruta del fileB
y siga tomando la subcadena desde 0 hasta el primer índice de /
. A continuación, compruebe la subcadena. Si es ..
luego elimine la subcadena de allí y elimine la subcadena de fileA''s
ruta del fileA''s
de lastIndexOf(/)
a la longitud. Luego repita. De esa manera, está eliminando las carpetas que no necesita y las ... ..s
.
Asi que :
Ejemplo A:
-
C:/projects/project1/module7/submodule5/fileA
Ejemplo Bs:
../../module3/submodule9/subsubmodule32/fileB
->
C:/projects/project1/module3/submodule9/subsubmodule32/fileB
Si soluciono tu problema, podrías hacer algo como esto:
File a = new File("/some/abs/path");
File parentFolder = new File(a.getParent());
File b = new File(parentFolder, "../some/relative/path");
String absolute = b.getCanonicalPath(); // may throw IOException
String absolutePath = FileSystems.getDefault (). GetPath (mayBeRelativePath) .normalize (). ToAbsolutePath (). ToString ();