Estoy viendo un fragmento de código Java en este momento, y toma una ruta como una Cadena y obtiene su URL usando URL resource = ClassLoader.getSystemClassLoader().getResource(pathAsString);
, luego llama String path = resource.getPath()
y finalmente se ejecuta new File(path);
.
Ah, y también hay llamadas a URL url = resource.toURI();
y String file = resource.getFile()
.
Estoy totalmente confundido en este momento, sobre todo por la terminología, supongo. ¿Alguien puede explicarme las diferencias o proporcionar algunos enlaces a material a prueba de falsificaciones? ¿Especialmente URI a URL y recurso a archivo ? Para mí, parece que deberían ser lo mismo, respectivamente ...
La diferencia entre getFile()
y getPath()
se explica aquí: ¿Cuál es la diferencia entre url.getFile () y getpath ()? (Curiosamente, ambos parecen devolver Strings, lo que probablemente agrega mucho a mi estado de ánimo ...)
Ahora, si tengo un localizador que hace referencia a una clase o paquete en un archivo jar, ¿diferirán esos dos (es decir, la ruta y las cadenas de archivo)?
resource.toString()
te daría jar:file:/C:/path/to/my.jar!/com/example/
, después de todo (nota el signo de exclamación).
¿Es la diferencia entre URI y URL en Java que el primero no codifica espacios? Cf. Archivos, URI y URL que entran en conflicto en Java (esta respuesta explica bastante bien la diferencia conceptual general entre los dos términos: los URI identifican y las URL localizan; )
Por último, y lo más importante, ¿por qué necesito un File
objeto? ¿Por qué un Resource ( URL
) no es suficiente? (¿Y hay un objeto de recurso?)
Lo siento si esta pregunta está un poco desorganizada; solo refleja la confusión que tengo ... :)
fuente
Path
y FileSystem de NIO :)URL
es opaco , como lo muestrajar:file:
, es decir, un recurso en un.jar
archivo.File
Es muy poco probable que meter eso en un resultado en algo útil.Respuestas:
ACTUALIZACIÓN 2017-04-12 ¡ Compruebe la respuesta de JvR ya que contiene una explicación más exhaustiva y exacta!
Tenga en cuenta que no me considero 100% competente para responder, pero sin embargo, aquí hay algunos comentarios:
File
representa un archivo o directorio accesible a través del sistema de archivosURL#getPath
es getter en la parte de la ruta de URL (protocol://host/path?query
)URL#getFile
según devoluciones de JavaDocpath+query
En Java,
URI
es solo una estructura de datos para manipular el identificador genérico en sí.URL
por otro lado, es realmente un localizador de recursos y le ofrece funciones para leer el recurso a través de correos electrónicos registradosURLStreamHandler
.Las URL pueden conducir a recursos del sistema de archivos y puede construir una URL para cada recurso del sistema de archivos utilizando el
file://
protocolo (de ahí la relaciónFile
<->URL
).También tenga en cuenta que eso
URL#getFile
no está relacionado conjava.io.File
.Es suficiente. Solo si desea pasar el recurso a algún componente que solo puede funcionar con archivos, debe obtenerlo
File
. Sin embargo, no todas las URL de recursos se pueden convertir aFile
s.Desde el punto de vista de JRE, es solo un término. Algunos marcos le proporcionan dicha clase (por ejemplo, Spring's Resource ).
fuente
java.nio.file.Path
, que es básicamente un reemplazo de (Java 7+)java.io.File
, ya que la última API aparentemente fue mal pensada en los primeros días de Java.La terminología es confusa y a veces confusa, y en su mayoría nace de la evolución de Java como API y como plataforma a lo largo del tiempo. Para comprender cómo estos términos llegaron a significar lo que hacen, es importante reconocer dos cosas que influyen en el diseño de Java:
Analizaré los conceptos y cómo surgieron. Responderé a sus otras preguntas específicas después de eso, porque es posible que tenga que referirme a algo en la primera parte.
¿Qué es un "recurso"?
Un dato abstracto y genérico que se puede localizar y leer. En términos generales, Java usa esto para referirse a un "archivo" que puede no ser un archivo pero que representa un dato con nombre. No tiene una clase directa o una representación de interfaz en Java , pero debido a sus propiedades (localizable, legible) a menudo se representa mediante una URL.
Debido a que uno de los primeros objetivos de diseño de Java era ejecutarse dentro de un navegador, como una aplicación de espacio aislado (¡applets!) Con derechos / privilegios / autorización de seguridad muy limitados, Java marca una diferencia clara (teórica) entre un archivo (algo en el local sistema de archivos) y un recurso (algo que necesita leer). Esta es la razón por la que leer algo relativo a la aplicación (iconos, archivos de clase, etc.) se realiza a
ClassLoader.getResource
través de la clase File y no a través de ella.Desafortunadamente, debido a que "recurso" también es un término genérico útil fuera de esta interpretación, también se usa para nombrar cosas muy específicas (por ejemplo, clase ResourceBundle , UIResource , Resource ) que no son, en este sentido, un recurso.
Las clases principales que representan (una ruta a) un recurso son java.nio.file.Path , java.io.File , java.net.URI y java.net.URL .
Archivo (java.io, 1.0)
La clase File representa un recurso al que se puede acceder a través del sistema de archivos nativo de la plataforma . Contiene solo el nombre del archivo, por lo que en realidad es más una ruta (ver más adelante) que la plataforma host interpreta de acuerdo con su propia configuración, reglas y sintaxis.
Tenga en cuenta que el archivo no necesita apuntar a algo local , solo algo que la plataforma de host entiende en el contexto del acceso al archivo, por ejemplo, una ruta UNC en Windows. Si monta un archivo ZIP como un sistema de archivos en su sistema operativo, File leerá sus entradas contenidas sin problemas.
URL (java.net, 1.0)
Junto con el concepto de recurso, la URL representa ese recurso de la misma manera que la clase File representa un archivo en la plataforma de host: como una cadena estructurada que apunta a un recurso. La URL además contiene un esquema que sugiere cómo llegar al recurso (con "archivo:" siendo "preguntar a la plataforma de host"), y así permite apuntar a recursos a través de HTTP, FTP, dentro de un JAR y otras cosas.
Desafortunadamente, las URL vienen con su propia sintaxis y terminología, incluido el uso de "archivo" y "ruta". En caso de que la URL sea una URL de archivo, URL.getFile devolverá una cadena idéntica a la cadena de ruta del archivo referenciado.
Class.getResource
devuelve una URL: es más flexible que devolver un archivo, y ha respondido a las necesidades del sistema como se imaginaba a principios de la década de 1990.URI (java.net, 1.4)
URI es una abstracción (leve) sobre URL. La diferencia entre URI y URL es conceptual y principalmente académica, pero URI se define mejor en un sentido formal y cubre una gama más amplia de casos de uso. Debido a que URL y URI son / no eran lo mismo, se introdujo una nueva clase para representarlos, con los métodos URI.toURL y URL.toURI para moverse entre uno y otro.
En Java, la principal diferencia entre URL y URI es que una URL conlleva la expectativa de poder resolverse , algo de lo que la aplicación podría querer un InputStream; un URI se trata más como una cosa abstracta que puede apuntar a algo que se puede resolver (y generalmente lo hace), pero lo que significa y cómo llegar a él está más abierto al contexto y la interpretación.
Ruta (java.nio.file, 1.7)
La nueva API de archivo, iconificada en la interfaz Path, permite una flexibilidad mucho mayor que la que podría ofrecer la clase File. La interfaz Path es una abstracción de la clase File y es parte de la API New IO File . Donde Archivo necesariamente apunta a un "archivo" como lo entiende la plataforma de host, Path es más genérico: representa un archivo (recurso) en un sistema de archivos arbitrario .
Path elimina la dependencia del concepto de archivo de la plataforma de host. Podría ser una entrada en un archivo ZIP, un archivo accesible a través de FTP o SSH-FS, una representación de múltiples raíces de la ruta de clases de la aplicación, o realmente cualquier cosa que se pueda representar de manera significativa a través de la interfaz FileSystem y su controlador, FileSystemProvider. Aporta el poder de "montar" sistemas de archivos en el contexto de una aplicación Java.
La plataforma de host se representa a través del "sistema de archivos predeterminado"; cuando llama
File.toPath
, obtiene una ruta en el sistema de archivos predeterminado.Improbable. Si el archivo JAR está en el sistema de archivos local, no debe tener un componente de consulta, por lo que
URL.getPath
yURL.getFile
debe devolver el mismo resultado. Sin embargo, elija el que necesita: las URL de archivo pueden no tener normalmente componentes de consulta, pero seguro que podría agregar uno de todos modos.Es posible que la URL no sea suficiente porque Archivo le brinda acceso a datos de mantenimiento como permisos (legibles, de escritura, ejecutables), tipo de archivo (¿soy un directorio?) Y la capacidad de buscar y manipular el sistema de archivos local. Si estas son características que necesita, File o Path se las proporcionan.
No necesita Archivo si tiene acceso a Ruta. Sin embargo, algunas API más antiguas pueden requerir Archivo.
No, no lo hay. Hay muchas cosas nombradas así, pero no son un recurso en el sentido de
ClassLoader.getResource
.fuente
La respuesta de Pavel Horal es agradable.
Como él dice, la palabra "archivo" tiene significados totalmente diferentes (prácticamente sin relación) en
URL#getFile
vs.java.io.File
Puede que eso sea parte de la confusión.Solo para agregar:
Un recurso en Java es un concepto abstracto, una fuente de datos que se puede leer. La ubicación (o dirección) de un recurso está representada en Java por un
URL
objeto.Un recurso puede corresponder a un archivo normal en el sistema de archivos local (específicamente, cuando
URL
comienza confile://
). Pero un recurso es más general (también puede ser algún archivo almacenado en un jar, o algunos datos para leer de la red, o de la memoria, o ...). Y también es más limitado, porqueFile
(además de ser algo más que un archivo normal: un directorio, un enlace) también se puede crear y escribir.Recuerde que en Java un
File
objeto no representa realmente "un archivo" sino la ubicación (el nombre completo, con la ruta) de un archivo. Por lo tanto, unFile
objeto le permite ubicar (y abrir) un archivo, yaURL
que le permite acceder (y abrir) un recurso. (¡No hay unaResource
clase en Java para representar un recurso, pero tampoco hay una para representar un archivo! Una vez más:File
no es un archivo, es la ruta de un archivo).fuente
Según tengo entendido, podría categorizarlos de la siguiente manera:
Basado en web: URI y URL.
Y local: recurso, ruta y archivos
Sería más fácil si se fusionaran en una sola clase; son realmente confusos: D
Espero que esto te ayude :)
(Acabo de echar un vistazo a la documentación, mire docs.oracle.com)
fuente
Un archivo es una representación abstracta de una entidad en el sistema de archivos local.
Una ruta es generalmente una cadena que indica la ubicación de un archivo dentro de un sistema de archivos. Por lo general, no incluye el nombre del archivo. Entonces c: \ documentos \ mystuff \ stuff.txt tendría una ruta con el valor de "C: \ documentos \ mystuff" Obviamente, el formato de los nombres de archivo absolutos y las rutas variaría enormemente de un sistema de archivos a otro.
URL es un conjunto de URI con URL que generalmente representa recursos accesibles a través de http. No creo que haya ningún tipo de regla rígida sobre cuándo algo tiene que ser un URI frente a una URL. Los URI son cadenas en forma de "protocolo: // identificador de recursos", como bitcoin: // params, http://something.com?param=value . Las clases como URL generalmente envuelven la cadena y proporcionan métodos de utilidad que String no tendría ninguna razón para proporcionar.
No existe el recurso, al menos no en el sentido del que estás hablando. El hecho de que un método se llame getResource no significa que devuelva un objeto de tipo Resource.
En última instancia, la mejor manera de averiguar qué hacen los métodos de una clase es crear una instancia de ella en su código, llamar a los métodos y luego pasar por el modo de depuración o enviar los resultados a System.out.
fuente