Je suis totalement confus en ce moment - principalement à cause de la terminologie, je suppose. Quelqu'un peut-il s'il vous plaît me guider à travers les différences ou fournir quelques liens vers du matériel factice? Surtout URI vers URL et ressource vers fichier? Pour moi, j'ai l'impression qu'ils devraient être la même chose, respectivement ...
La terminologie est déroutante et parfois déroutante, et est principalement née de l'évolution de Java en tant qu'API et en tant que plate-forme au fil du temps. Pour comprendre comment ces termes ont fini par signifier ce qu'ils font, il est important de reconnaître deux choses qui influencent la conception de Java:
- Rétrocompatibilité. Les anciennes applications doivent fonctionner sur des installations plus récentes, idéalement sans modification. Cela signifie qu'une ancienne API (avec ses noms et sa terminologie) doit être maintenue dans toutes les versions les plus récentes.
- Multiplateforme. L'API doit fournir une abstraction utilisable de sa plate-forme sous-jacente, qu'il s'agisse d'un système d'exploitation ou d'un navigateur.
Je vais parcourir les concepts et comment ils sont nés. Je répondrai à vos autres questions précises après cela, car je devrai peut-être faire référence à quelque chose dans la première partie.
Qu'est-ce qu'une «ressource»?
Un élément de données abstrait et générique qui peut être localisé et lu. En clair, Java l'utilise pour désigner un «fichier» qui n'est peut-être pas un fichier mais qui représente une donnée nommée. Il n'a pas de représentation directe de classe ou d'interface en Java , mais en raison de ses propriétés (localisables, lisibles), il est souvent représenté par une URL.
Parce que l'un des premiers objectifs de conception de Java était d'être exécuté à l'intérieur d'un navigateur, en tant qu'application sandbox (applets!) Avec des droits / privilèges / habilitation de sécurité très limités, Java fait une différence claire (théorique) entre un fichier (quelque chose sur le système de fichiers) et une ressource (quelque chose qu'il doit lire). C'est pourquoi la lecture de quelque chose relatif à l'application (icônes, fichiers de classe, etc.) se fait via ClassLoader.getResource
et non via la classe File.
Malheureusement, parce que "ressource" est également un terme générique utile en dehors de cette interprétation, il est également utilisé pour nommer des choses très spécifiques (par exemple, classe ResourceBundle , UIResource , Resource ) qui ne sont pas, dans ce sens, une ressource.
Les principales classes représentant (un chemin vers) une ressource sont java.nio.file.Path , java.io.File , java.net.URI et java.net.URL .
Fichier (java.io, 1.0)
Une représentation abstraite des chemins de fichiers et de répertoires.
La classe File représente une ressource accessible via le système de fichiers natif de la plateforme . Il ne contient que le nom du fichier, il s'agit donc plutôt d'un chemin (voir plus loin) que la plateforme hôte interprète selon ses propres paramètres, règles et syntaxe.
Notez que File n'a pas besoin de pointer vers quelque chose de local , juste quelque chose que la plate-forme hôte comprend dans le contexte de l'accès aux fichiers, par exemple un chemin UNC dans Windows. Si vous montez un fichier ZIP en tant que système de fichiers dans votre système d'exploitation, File lira très bien ses entrées contenues.
URL (java.net, 1.0)
L'URL de classe représente un localisateur de ressources uniforme, un pointeur vers une «ressource» sur le World Wide Web. Une ressource peut être quelque chose d'aussi simple qu'un fichier ou un répertoire, ou il peut s'agir d'une référence à un objet plus complexe, comme une requête à une base de données ou à un moteur de recherche.
En tandem avec le concept de ressource, l'URL représente cette ressource de la même manière que la classe File représente un fichier dans la plate-forme hôte: sous la forme d' une chaîne structurée qui pointe vers une ressource. URL contient en plus un schéma qui indique comment atteindre la ressource (avec "file:" étant "demander à la plate-forme hôte"), et permet ainsi de pointer vers les ressources via HTTP, FTP, dans un JAR, etc.
Malheureusement, les URL ont leur propre syntaxe et terminologie, y compris l'utilisation de «fichier» et «chemin». Dans le cas où l'URL est une URL de fichier, URL.getFile renverra une chaîne identique à la chaîne de chemin du fichier référencé.
Class.getResource
renvoie une URL: il est plus flexible que le renvoi de File, et il a répondu aux besoins du système comme imaginé au début des années 1990.
URI (java.net, 1.4)
Représente une référence URI (Uniform Resource Identifier).
L'URI est une (légère) abstraction sur l'URL. La différence entre l'URI et l'URL est conceptuelle et principalement académique, mais l'URI est mieux définie dans un sens formel et couvre un plus large éventail de cas d'utilisation. Parce qu'URL et URI sont / n'étaient pas la même chose, une nouvelle classe a été introduite pour les représenter, avec les méthodes URI.toURL et URL.toURI pour se déplacer entre l'une et l'autre.
En Java, la principale différence entre l'URL et l'URI est qu'une URL est censée être résoluble , ce dont l'application peut souhaiter un InputStream; un URI est traité plus comme un thingamajig abstrait qui pourrait pointer vers quelque chose de résoluble (et le fait généralement), mais ce que cela signifie et comment l'atteindre sont plus ouverts au contexte et à l'interprétation.
Chemin (java.nio.file, 1.7)
Un objet qui peut être utilisé pour localiser un fichier dans un système de fichiers. Il représentera généralement un chemin de fichier dépendant du système.
La nouvelle API de fichier, iconifiée dans l'interface Path, permet une flexibilité beaucoup plus grande que celle que la classe File pourrait offrir. L'interface Path est une abstraction de la classe File et fait partie de l' API New IO File . Où File pointe nécessairement vers un "fichier" tel que compris par la plateforme hôte, Path est plus générique: il représente un fichier (ressource) dans un système de fichiers arbitraire .
Path supprime la dépendance au concept de fichier de la plate-forme hôte. Il peut s'agir d'une entrée dans un fichier ZIP, d'un fichier accessible via FTP ou SSH-FS, une représentation multi-racine du chemin de classe de l'application, ou vraiment tout ce qui peut être représenté de manière significative via l'interface FileSystem et son pilote, FileSystemProvider. Il apporte la puissance de "monter" des systèmes de fichiers dans le contexte d'une application Java.
La plate-forme hôte est représentée par le "système de fichiers par défaut"; lorsque vous appelez File.toPath
, vous obtenez un chemin sur le système de fichiers par défaut.
Maintenant, si j'ai un localisateur qui fait référence à une classe ou à un package dans un fichier jar, ces deux (c'est-à-dire le chemin et les chaînes de fichiers) seront-ils différents?
Improbable. Si le fichier jar est sur le système de fichiers local, vous ne devriez pas avoir un composant de requête, donc URL.getPath
et URL.getFile
doit retourner le même résultat. Cependant, choisissez celui dont vous avez besoin: les URL de fichiers peuvent généralement ne pas avoir de composants de requête, mais je pourrais certainement en ajouter un de toute façon.
Enfin - et surtout - pourquoi ai-je besoin d'un objet File; pourquoi une ressource (URL) n'est-elle pas suffisante?
L'URL peut ne pas être suffisante car File vous donne accès à des données de gestion telles que les autorisations (lisibles, inscriptibles, exécutables), le type de fichier (suis-je un répertoire?), Et la possibilité de rechercher et de manipuler le système de fichiers local. Si ce sont des fonctionnalités dont vous avez besoin, File ou Path les fournit.
Vous n'avez pas besoin de File si vous avez accès à Path. Cependant, certaines API plus anciennes peuvent nécessiter un fichier.
(Et y a-t-il un objet Resource?)
Non, il n'y en a pas. Il y a beaucoup de choses nommées comme ça, mais elles ne sont pas une ressource au sens de ClassLoader.getResource
.
Path
et FileSystem de NIO :)