¿Cómo resuelve Java una ruta relativa en new File ()?
Estoy tratando de entender la forma en que Java resuelve la ruta relativa al crear un objeto File
.
Sistema operativo utilizado: Windows
Para el siguiente fragmento, estoy obteniendo un IOException
ya que no puede encontrar la ruta:
@Test
public void testPathConversion() {
File f = new File("test/test.txt");
try {
f.createNewFile();
System.out.println(f.getPath());
System.out.println(f.getAbsolutePath());
System.out.println(f.getCanonicalPath());
} catch (Exception e) {
e.printStackTrace();
}
}
Lo que entiendo aquí es que Java trata la ruta proporcionada como absoluta y devuelve un error cuando la ruta no existe. Así que tiene sentido.
Cuando actualizo el código anterior para usar la ruta relativa:
@Test
public void testPathConversion() {
File f = new File("test/../test.txt");
try {
f.createNewFile();
System.out.println(f.getPath());
System.out.println(f.getAbsolutePath());
System.out.println(f.getCanonicalPath());
} catch (Exception e) {
e.printStackTrace();
}
}
Crea un nuevo archivo y proporciona la siguiente salida:
test\..\test.txt
C:\JavaForTesters\test\..\test.txt
C:\JavaForTesters\test.txt
En este caso, mi suposición es, a pesar de que la ruta proporcionada no existe, porque la ruta contiene "/../ ", java trata esto como una ruta relativa y crea el archivo en el user.dir
. Así que esto también tiene sentido.
Pero si actualizo la ruta relativa como se muestra a continuación:
@Test
public void testPathConversion() {
File f = new File("test/../../test.txt");
try {
f.createNewFile();
System.out.println(f.getPath());
System.out.println(f.getAbsolutePath());
System.out.println(f.getCanonicalPath());
} catch (Exception e) {
e.printStackTrace();
}
}
Entonces obtengo IOException: El acceso está denegado.
Mis preguntas son:
- por qué
"test/../test.txt"
se trata como una ruta relativa y crea el archivo en"user.dir"
pero"test/../../test.txt"
devuelve un error? ¿Dónde intenta crear el archivo para la ruta"test/../../test.txt"
? -
Cuando no se encuentra la ruta relativa especificada, el archivo parece estar creado en
user.dir
. Por lo tanto, me parece que los dos escenarios siguientes hacen lo mismo://scenario 1 File f = new File("test/../test.txt"); f.createNewFile(); //scenario 2 File f = new File("test.txt"); f.createNewFile();
Entonces, ¿hay un caso del mundo real en el que uno usaría el escenario 1 en lugar del escenario 2?
Supongo que me estoy perdiendo algo obvio aquí o he malentendido fundamentalmente los caminos relativos. Fui a través de los documentos de Java para el archivo y no soy capaz de encontrar una explicación para esto. Hay bastantes preguntas publicadas en Stack Overflow con respecto a las rutas relativas, pero las que busqué fueron para escenarios específicos y no exactamente sobre cómo se resuelven las rutas relativas.
Sería genial si alguien pudiera explicarme cómo funciona esto o señalar algunos enlaces relacionados.
6 answers
Hay un concepto de working directory
.
Este directorio está representado por un .
(punto).
En rutas relativas, todo lo demás es relativo a ella.
En pocas palabras, el .
(el directorio de trabajo) es donde se ejecuta el programa.
En algunos casos se puede cambiar el directorio de trabajo, pero en general esto es
lo que representa el punto. Creo que esto es C:\JavaForTesters\
en su caso.
Así que test\..\test.txt
significa: el subdirectorio test
en mi directorio de trabajo, luego un nivel arriba, entonces el
file test.txt
. Esto es básicamente lo mismo que solo test.txt
.
Para más detalles, consulte aquí.
Http://docs.oracle.com/javase/7/docs/api/java/io/File.html
Http://docs.oracle.com/javase/tutorial/essential/io/pathOps.html
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-11 10:26:28
Cuando su ruta comienza con un directorio raíz, es decir, C:\
en windows o /
en Unix o en la ruta de recursos de java, se considera una ruta absoluta. Todo lo demás es relativo, así que
new File("test.txt") is the same as new File("./test.txt")
new File("test/../test.txt") is the same as new File("./test/../test.txt")
La principal diferencia entre getAbsolutePath
y getCanonicalPath
es que el primero concatena un camino padre y un camino hijo, por lo que puede contener puntos: ..
o .
. getCanonicalPath
siempre devolverá la misma ruta para un archivo en particular.
Nota: File.equals
utiliza una forma abstracta de una ruta (getAbsolutePath
) para comparar archivos, así que esto significa que dos File
objetos para el mismo podrían no ser iguales y File
s no son seguros para usar en colecciones como Map
o Set
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-12-15 17:29:24
El directorio de trabajo es un concepto común en prácticamente todos los sistemas operativos y lenguajes de programas, etc. Es el directorio en el que se está ejecutando el programa. Esto suele ser (pero no siempre, hay formas de cambiarlo) el directorio en el que se encuentra la aplicación.
Las rutas relativas son aquellas que comienzan sin un especificador de unidad. Así que en Linux no comienzan con un /
, en Windows no comienzan con un C:\
, etc. Estos siempre comienzan desde su directorio de trabajo.
Absoluto las rutas son las que comienzan con un especificador de unidad (o máquina para rutas de red). Siempre van desde el inicio de ese viaje.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-01-11 10:18:50
En windows y Netbeans puede establecer la ruta relativa como:
new FileReader("src\\PACKAGE_NAME\\FILENAME");
En Linux y Netbeans puede establecer la ruta relativa como:
new FileReader("src/PACKAGE_NAME/FILENAME");
Si tienes tu código dentro Source Packages
No sé si es lo mismo para eclipse u otro IDE
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-12 10:42:03
Solo está ligeramente relacionado con la pregunta, pero trata de envolver tu cabeza alrededor de esta. Así que no intuitivo:
import java.nio.file.*;
class Main {
public static void main(String[] args) {
Path p1 = Paths.get("/personal/./photos/./readme.txt");
Path p2 = Paths.get("/personal/index.html");
Path p3 = p1.relativize(p2);
System.out.println(p3); //prints ../../../../index.html !!
}
}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-09-10 18:48:32
Las rutas relativas pueden entenderse mejor si sabe cómo Java ejecuta el programa.
Existe un concepto de directorio de trabajo cuando se ejecutan programas en Java. Asumiendo que tienes una clase, digamos, FileHelper
que hace el IO bajo
/User/home/Desktop/projectRoot/src/topLevelPackage/
.
Dependiendo del caso en el que invoque java
para ejecutar el programa, tendrá un directorio de trabajo diferente. Si ejecuta su programa desde dentro y desde el IDE, lo más probable es que sea projectRoot
.
En este caso
$ projectRoot/src : java topLevelPackage.FileHelper
serásrc
.En este caso
$ projectRoot : java -cp src topLevelPackage.FileHelper
seráprojectRoot
.En este caso
$ /User/home/Desktop : java -cp ./projectRoot/src topLevelPackage.FileHelper
seráDesktop
.
(Assuming $ is your command prompt with standard Unix-like FileSystem. Similar correspondence/parallels with Windows system)
Por lo tanto, su ruta relativa raíz (.)
se resuelve en su directorio de trabajo. Por lo tanto, para estar mejor seguro de dónde escribir archivos, se dice que considere el enfoque a continuación.
package topLevelPackage
import java.io.File;
import java.nio.file.Path;
import java.nio.file.Paths;
public class FileHelper {
// Not full implementation, just barebone stub for path
public void createLocalFile() {
// Explicitly get hold of working directory
String workingDir = System.getProperty("user.dir");
Path filePath = Paths.get(workingDir+File.separator+"sampleFile.txt");
// In case we need specific path, traverse that path, rather using . or ..
Path pathToProjectRoot = Paths.get(System.getProperty("user.home"), "Desktop", "projectRoot");
System.out.println(filePath);
System.out.println(pathToProjectRoot);
}
}
Espero que esto ayude.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-05-22 16:55:58