web-dev-qa-db-fra.com

Quelle est la différence entre une ressource, un URI, une URL, un chemin d'accès et un fichier en Java?

Je regarde un morceau de code Java pour le moment), et il prend un chemin d'accès sous forme de chaîne et obtient son URL en utilisant URL resource = ClassLoader.getSystemClassLoader().getResource(pathAsString);, puis appelle String path = resource.getPath() et finalement exécute new File(path);.

Oh, et il y a aussi des appels à URL url = resource.toURI(); et String file = resource.getFile().

Je suis totalement confus en ce moment - principalement à cause de la terminologie, je suppose. Quelqu'un peut-il me décrire les différences ou fournir quelques liens vers du matériel factice? En particulier, URI vers URL et Ressource dans un fichier? Pour moi, c'est comme si elles devaient être la même chose, respectivement ...

La différence entre getFile() et getPath() est expliqué ici: Quelle est la différence entre url.getFile () et getpath ()? (Fait intéressant, ils semblent tous deux renvoyer des chaînes, ce qui ajoute probablement beaucoup à mon état d'esprit. ..)

Maintenant, si j’ai un localisateur qui référence une classe ou un package dans un fichier jar, ces deux noms (c.-à-d. Chemin et chaîne de fichier) seront-ils différents?

resource.toString() vous donnerait jar:file:/C:/path/to/my.jar!/com/example/, après tout (notez le point d’exclamation).

Est la différence entre [~ # ~] uri [~ # ~] et [~ # ~] url [ ~ # ~] en Java le premier ne code pas les espaces? Cf. Fichiers, URI et URL conflictuels en Java (Cette réponse explique assez bien la différence générale, conceptuelle entre les deux termes: Les URI identifient et les URL se localisent ; )

Enfin - et surtout - pourquoi ai-je besoin de File object; pourquoi une ressource (URL) ne suffit-elle pas? (et y a-t-il un objet Resource?)

Désolé si cette question est un peu inorganisée; ça reflète juste la confusion que j'ai ... :)

86
Christian

UPDATE 2017-04-12 Vérifiez réponse de JvR car il contient une explication plus exhaustive et plus exacte!


Veuillez noter que je ne me considère pas à 100% compétent pour répondre, mais voici néanmoins quelques commentaires:

  • File représente un fichier ou un répertoire accessible via le système de fichiers
  • ressource est un terme générique pour un objet de données pouvant être chargé par l'application
    • habituellement ressources sont des fichiers distribués avec l'application/bibliothèque et chargés via le mécanisme de chargement de classe (lorsqu'ils résident sur le chemin de classe)
  • URL#getPath est un getter sur la partie chemin de l’URL (protocol://Host/path?query)
  • URL#getFile selon JavaDoc renvoie path+query

En Java, URI n'est qu'une structure de données permettant de manipuler l'identifiant générique lui-même.

Par contre, URL est en réalité un localisateur de ressources et vous offre des fonctionnalités permettant de lire la ressource via les URLStreamHandlers enregistrés.

Les URL peuvent mener aux ressources du système de fichiers et vous pouvez construire une URL pour chaque ressource du système de fichiers à l'aide de file:// protocole (d'où la relation File <-> URL).

Sachez également que cela URL#getFile n'a aucun lien avec Java.io.File.


Pourquoi ai-je besoin de l'objet File? pourquoi une ressource (URL) n'est-elle pas suffisante?

C'est assez. Si vous voulez transmettre la ressource à un composant qui ne peut fonctionner qu'avec des fichiers, vous devez en obtenir File. Cependant, toutes les URL de ressources ne peuvent pas être converties en Files.

Et y a-t-il un objet Resource?

Du point de vue de la JRE, ce n'est qu'un terme. Certains frameworks vous fournissent une telle classe (par exemple, Ressource de Spring ).

40
Pavel Horal

Je suis totalement confus en ce moment - principalement à cause de la terminologie, je suppose. Quelqu'un peut-il me décrire les différences ou fournir quelques liens vers du matériel factice? Surtout URI à l'URL et ressource à classer? Pour moi, c'est comme si elles devaient être la même chose, respectivement ...

La terminologie est déroutante et parfois déconcertante, et découle principalement de l'évolution de Java en tant qu'API et en tant que plate-forme au fil du temps. Pour comprendre comment ces termes sont venus à signifier ce qu'ils font, il est important de reconnaître deux choses qui influencent la conception de Java:

  • Compatibilité avec les versions antérieures Les anciennes applications doivent s'exécuter sur des installations plus récentes, idéalement sans modification. Cela signifie qu'une ancienne API (avec ses noms et sa terminologie) doit être conservée dans toutes les versions les plus récentes.
  • multiplate-forme. L'API doit fournir une abstraction utilisable de la plate-forme sous-jacente, qu'il s'agisse d'un système d'exploitation ou d'un navigateur.

Je vais passer en revue les concepts et comment ils sont apparus. Je répondrai ensuite à vos autres questions spécifiques, car je pourrais devoir faire référence à quelque chose dans la première partie.

Qu'est-ce qu'une "ressource"?

Une donnée abstraite et générique pouvant être localisée et lue. Autrement dit, Java utilise ce terme pour faire référence à un "fichier" pouvant ne soit pas un fichier mais représente une donnée nommée. Il n’a pas de représentation directe de classe ou d’interface en Java , mais à cause de ses propriétés (localisable, lisible), il est souvent représenté par une URL.

Comme l'un des premiers objectifs de conception de Java devait être exécuté dans un navigateur, en tant qu'application en mode bac à sable (applets!) Avec des droits/privilèges/autorisation de sécurité très limités, , Java établit une différence claire (théorique) entre un fichier (quelque chose sur le système de fichiers local) et une ressource (quelque chose qu'il a besoin de lire). C'est pourquoi la lecture de quelque chose relatif à l'application (icônes, fichiers de classe, etc.) s'effectue par ClassLoader.getResource et non par la classe File.

Malheureusement, parce que "ressource" est aussi un terme générique utile extérieur de cette interprétation, il est également utilisé pour nommer des choses très spécifiques (par exemple, la classe ResourceBundle , IResource , Ressource ) qui ne sont pas, en ce sens, une ressource.

Les classes principales représentant un chemin d'accès à 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 bien d’un chemin (voir plus loin) que la plate-forme hôte interprète selon ses propres paramètres, règles et syntaxe.

Notez que File n'a pas besoin de pointer sur quelque chose local, mais simplement sur quelque chose que la plate-forme hôte comprend dans le contexte de l'accès aux fichiers, par exemple. un chemin UNC sous Windows. Si vous montez un fichier Zip en tant que système de fichiers dans votre système d'exploitation, File lira correctement les entrées qu'il contient.

URL (Java.net, 1.0)

L'URL de classe représente un localisateur de ressources uniforme, un pointeur sur une "ressource" sur le World Wide Web. Une ressource peut être quelque chose d'aussi simple qu'un fichier ou un répertoire, ou peut être une référence à un objet plus compliqué, tel qu'une requête à une base de données ou à un moteur de recherche.

Parallèlement au concept de ressource, l'URL représente cette ressource de la même manière que la classe File représente un fichier sur la plateforme de l'hôte: sous la forme d'une chaîne structurée qui pointe vers une ressource. L'URL contient en outre un schéma qui indique comment accéder à la ressource (avec "fichier:" étant "demander à la plate-forme hôte"), et permet ainsi de pointer les ressources via HTTP, FTP, dans un fichier JAR, etc.

Malheureusement, les URL ont leur propre syntaxe et leur propre terminologie, y compris l'utilisation de "fichier" et "chemin". Si 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: elle est plus flexible que celle de File et répond aux besoins du système, comme on l’imaginait au début des années 90.

URI (Java.net, 1.4)

Représente une référence d'identificateur de ressource uniforme (URI).

L'URI est une (légère) abstraction sur l'URL. La différence entre l'URI et l'URL est conceptuelle et essentiellement académique, mais l'URI est mieux définie au sens formel et couvre un plus grand nombre de cas d'utilisation. Les adresses URL et URI n'étant pas/étant identiques, une nouvelle classe a été introduite pour les représenter, avec les méthodes URI.toURL et URL.toURI pour passer de l'une à l'autre.

En Java, la principale différence entre l'URL et l'URI réside dans le fait que une URL indique être résolue , ce à quoi l'application pourrait vouloir un InputStream; un URI est traité plus comme un objet abstrait qui pourrait indique quelque chose qui peut être résolu (et le fait généralement), mais ce que cela signifie et comment l'atteindre est plus ouvert au contexte et à l'interprétation.

Path (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é bien supérieure à celle de la classe File. L’interface Path est une abstraction de la classe File et fait partie de New IO API de fichier . Où File pointe nécessairement vers un "fichier" tel que compris par la plate-forme hôte, Path est plus générique: il représente un fichier (ressource) dans un système de fichiers arbitraire.

Path supprime le recours 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, d'une représentation multi-racines du chemin d'accès aux classes de l'application ou de tout élément pouvant être représenté de manière significative via l'interface FileSystem et son pilote, FileSystemProvider. Il apporte la puissance du "montage" 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"; quand vous appelez File.toPath, vous obtenez un chemin sur le système de fichiers par défaut.


Maintenant, si j’ai un localisateur qui référence une classe ou un package dans un fichier jar, ces deux noms (c.-à-d. Chemin et chaîne de fichier) seront-ils différents?

Peu probable. Si le fichier jar se trouve sur le système de fichiers local, vous ne devriez pas avoir de composant de requête, donc URL.getPath et URL.getFile devrait retourner le même résultat. Cependant, choisissez celui dont vous avez besoin: les URL de fichier ne peuvent généralement pas contenir de composants de requête, mais je pourrais néanmoins en ajouter un.

Enfin et surtout, pourquoi ai-je besoin de l’objet File? pourquoi une ressource (URL) n'est-elle pas suffisante?

L'URL peut ne pas suffire car File vous donne accès à des données de maintenance 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, Fichier ou Chemin les fournit.

Vous n'avez pas besoin de File si vous avez accès à Path. Certaines API plus anciennes peuvent toutefois nécessiter un fichier.

(Et y a-t-il un objet Ressource?)

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.

40
JvR

La réponse de Pavel Horal c'est Nice.

Comme il le dit, le mot "fichier" a des significations totalement différentes (pratiquement non apparentées) dans URL#getFile contre Java.io.File - peut être que cela fait partie de la confusion.

Juste pour ajouter:

  • Une ressource dans Java est un concept abstrait, une source de données pouvant être lue. L'emplacement (ou l'adresse ) d’une ressource est représentée dans Java par un objet URL.

  • Une ressource peut correspondre à un fichier normal dans le système de fichiers local (en particulier lorsque sa URL commence par file://). Mais une ressource est plus générale (il peut aussi s'agir d'un fichier stocké dans un fichier jar, de données à lire sur le réseau, ou de la mémoire, ou ...). Et c'est aussi plus limité, car un File (en plus d'être autre chose qu'un fichier normal: un répertoire, un lien) peut également être créé et écrit.

  • Rappelez-vous dans Java un objet File ne représente pas vraiment "un fichier" mais l'emplacement ( ainsi, un objet File vous permet de localiser (et d’ouvrir) un fichier, de même que URL vous permet d’accéder (et d’ouvrir) une ressource. (Il n'y a pas de Resource class dans Java pour représenter une ressource, mais il n'y en a pas non plus pour représenter un fichier! Une fois de plus: File n'est pas un fichier , c’est le chemin d’un fichier).

11
leonbloy

Si je comprends bien, vous pouvez les classer comme suit:

Basé sur le Web: URI et URL.

  • URL: une URL est un emplacement défini sur le site (uniquement une adresse Web normale telle que - stackoverflow.com)
  • URI: Ever URL est un URI. Mais les URI peuvent aussi contenir des choses comme "mailto:", ce qui en fait aussi quelques-uns de ce que je dirais d'un "script".

Et local: ressource, chemin et fichiers

  • Ressource: Les ressources sont des fichiers dans votre pot. Ils sont utilisés pour charger des fichiers à partir de bocaux/conteneurs.
  • Chemin: Un chemin est essentiellement une chaîne. Mais il est livré avec des fonctions pratiques pour concaténer plusieurs chaînes ou ajouter des fichiers à une chaîne. Cela garantit que le chemin que vous construisez est valide.
  • Fichier: Il s'agit d'une référence à un répertoire ou à un fichier. Il est utilisé pour modifier des fichiers, les ouvrir, etc.

Il serait plus facile de les fusionner en une seule classe - ils sont vraiment déroutants: D

J'espère que ceci vous aide :)

(Je viens de jeter un coup d'oeil à la documentation - regardez docs.Oracle.com)

3
Cyphrags

Un fichier est une représentation abstraite d'une entité dans le système de fichiers local.

Un chemin est généralement une chaîne indiquant l'emplacement d'un fichier dans un système de fichiers. Il n'inclut généralement pas le nom de fichier. Donc, c:\documents\mystuff\stuff.txt aurait un chemin avec la valeur "C:\documents\mystuff" Évidemment, le format des noms de fichiers absolus et des chemins varierait énormément d’un système de fichiers à l’autre.

L'URL est un sous-ensemble d'URI, l'URL représentant généralement les ressources accessibles via http. Je ne pense pas qu'il y ait une règle absolue à propos du moment où quelque chose doit être un URI par rapport à une URL. Les URI sont des chaînes sous la forme de "protocole: // ressource-identificateur" tel que bitcoin: // params, http://something.com?param=value . Des classes comme URL encapsulent généralement la chaîne et fournissent des méthodes utilitaires que String n’aurait aucune raison de fournir.

Aucune ressource comme ressource, du moins pas dans le sens dont vous parlez. Le fait qu'une méthode s'appelle getResource ne signifie pas qu'elle retourne un objet de type Resource.

En fin de compte, le meilleur moyen de déterminer les méthodes d'une classe consiste à en créer une instance dans votre code, à appeler les méthodes, puis à passer en mode débogage ou à envoyer les résultats à System.out.

0
Jim W