Java中的资源,URI,URL,path和文件有什么区别?

我正在查看一段Java代码,它将path作为一个string,并使用URL resource = ClassLoader.getSystemClassLoader().getResource(pathAsString);获取其URL URL resource = ClassLoader.getSystemClassLoader().getResource(pathAsString); ,然后调用String path = resource.getPath() ,最后执行new File(path);

哦,还有URL url = resource.toURI();String file = resource.getFile()

我现在完全困惑 – 主要是因为术语,我猜。 有人可以通过差异来引导我,或者提供一些链接到防伪材料吗? 尤其是URL和资源到文件的 URI? 对我来说,感觉就像他们应该是相同的东西,分别…

getFile()getPath() 之间的区别在这里解释: url.getFile()和getpath()之间有什么区别? (有趣的是,他们都似乎返回string,这可能会增加我的心态很多…)

现在,如果我有一个引用一个jar文件中的类或包的定位器,这两个(即path文件string)是不同的?

resource.toString()会给你jar:file:/C:/path/to/my.jar!/com/example/ ,毕竟(注意感叹号)。

Java中的URIURL之间的区别是前者不编码空格吗? 参看 在Java中冲突的文件,URI和URL (这个答案很好地解释了两个术语之间的一般概念上的区别: URI标识和URL定位 )

最后 – 也是最重要的 – 为什么我需要File对象; 为什么不是一个资源( URL )足够? (还有一个资源对象?)

对不起,如果这个问题有点没有组织; 它只是反映了我的困惑… 🙂

UPDATE 2017-04-12检查JvR的答案,因为它包含更详尽和精确的解释!


请注意,我不认为自己有100%的能力回答,但是这里有一些评论:

  • File表示可通过文件系统访问的文件或目录
  • 资源是可由应用程序加载的数据对象的通用术语
    • 通常资源是与应用程序/库一起分发的文件,并通过类加载机制加载(当它们驻留在类path中时)
  • URL#getPathURL#getPathpath部分的getter( protocol://host/path?query
  • 根据JavaDoc的URL#getFile返回path+query

在Java中, URI只是一个操作通用标识符本身的数据结构。

另一方面, URL实际上是一个资源定位器,并提供了通过注册的URLStreamHandler实际读取资源的function。

URL可以导致文件系统资源,您可以使用file:// protocol(因此File < – > URL关系)构造每个文件系统资源的URL

另请注意,该URL#getFilejava.io.File无关。


为什么我需要File对象; 为什么不是一个资源(URL)足够?

这就够了。 只有当你想将资源传递给一些只能使用文件的组件时,你需要从中获取File 。 但是并不是所有的资源URL都可以转换成File

有一个资源对象?

从JRE的angular度来看,这只是一个术语。 一些框架为您提供这样的类(例如Spring的资源 )。

我现在完全困惑 – 主要是因为术语,我猜。 有人可以通过差异来引导我,或者提供一些链接到防伪材料吗? 尤其是URL和资源到文件的URI? 对我来说,感觉就像他们应该是相同的东西,分别…

这个术语令人困惑,有时甚至是混乱,而且大多源于Java作为API和随着时间推移的平台的演变。 为了理解这些术语是如何expression他们所做的,重要的是要认识到影响Javadevise的两件事情:

  • 向后兼容。 旧的应用程序应运行在较新的安装上,理想情况下不需要修改。 这意味着需要通过所有新版本来维护旧的API(使用其名称和术语)。
  • 跨平台。 API应提供其底层平台的可用抽象,无论是操作系统还是浏览器。

我将通读这些概念以及它们是如何成为的。 之后我会回答你的其他具体问题,因为我可能不得不在第一部分中提到某些问题。

什么是“资源”?

可以定位和读取的抽象通用数据片段。 松散地说,Java使用这个来引用一个“文件”,它可能不是一个文件,而是代表一个有名的数据。 它在Java中没有直接的类或接口表示 ,但是由于它的属性(可定位的,可读的),它通常用URL来表示。

由于Java的早期devise目标之一是在浏览器内运行,作为具有非常有限的权限/特权/安全许可的沙盒应用程序(applets!),因此Java在文件(在本地文件系统)和一个资源(它需要读取的东西)。 这就是为什么通过ClassLoader.getResource而不是通过File类来读取与应用程序相关的东西(图标,类文件等等)的原因。

不幸的是,因为“资源” 这个解释之外也是一个有用的通用术语,所以它也被用来命名非常具体的东西(例如类ResourceBundle , UIResource , Resource ),在这个意义上,它不是资源。

代表资源(主要path)的主要类是java.nio.file.Path , java.io.File , java.net.URI和java.net.URL 。

File (java.io,1.0)

文件和目录path名的抽象表示。

File类表示可通过平台的本机文件系统访问的资源。 它只包含文件的名称,所以它实际上是更多的path(见后面),主机平台根据自己的设置,规则和语法来解释。

请注意,文件不需要指向本地的东西,只是主机平台在文件访问的上下文中可以理解的东西,例如Windows中的UNCpath。 如果您在您的操作系统中将ZIP文件作为文件系统安装,则File将读取其包含的条目。

URL (java.net,1.0)

类URL表示一个统一资源定位符,指向万维网上的“资源”。 资源可以像文件或目录一样简单,也可以是对更复杂对象的引用,例如对数据库的查询或search引擎。

与资源的概念相结合,URL代表该资源的方式与File类在主机平台中表示文件的方式相同:作为指向资源的结构化string。 URL还包含一个提示如何访问资源的scheme(“file:”是“询问主机平台”),因此允许通过HTTP,FTP,JAR内的指向资源,以及什么。

不幸的是,URLs有自己的语法和术语,包括使用“文件”和“path”。 如果URL是文件URL,则URL.getFile将返回与被引用文件的pathstring相同的string。

Class.getResource返回一个URL:它比返回File更灵活,它已经满足了90年代初想象中的系统需求。

URI (java.net,1.4)

表示统一资源标识符(URI)引用。

URI是对URL的(轻微)抽象。 URI和URL之间的区别是概念性的,主要是学术性的,但是URI在forms上更好地定义,涵盖了更广泛的用例。 因为URL和URI是不一样的,所以引入了一个新的类来表示它们,方法URI.toURL和URL.toURI在一个和另一个之间移动。

在Java中,URL和URI之间的主要区别在于URL 带有可parsing的期望,应用程序可能需要InputStream; 一个URI被视为更像是一个抽象的东西, 可能指向可parsing的东西(通常是),但是它的含义和如何达到它更容易接受上下文和解释。

Path (java.nio.file,1.7)

可用于在文件系统中查找文件的对象。 它通常代表一个依赖于系统的文件path。

Path接口中图标化的新文件API允许比File类提供更大的灵活性。 Path接口是File类抽象 ,是New IO File API的一部分 。 在File必须指向主机平台所理解的“文件”的情况下,Path更为通用:它代表任意文件系统中的文件(资源)。

path消除了对主机平台的文件概念的依赖。 它可能是ZIP文件中的一个条目,通过FTP或SSH-FS可访问的文件,应用程序类path的多重根源表示,或者是通过FileSystem接口及其驱动程序FileSystemProvider可以有意义地表示的任何内容。 它将“安装”文件系统的能力带入Java应用程序的上下文中。

主机平台通过“默认文件系统”来表示; 当你调用File.toPath ,你会在默认的文件系统上得到一个Path。


现在,如果我有一个引用一个jar文件中的类或包的定位器,这两个(即path文件string)是不同的?

不太可能。 如果jar文件位于本地文件系统上,则不应该有查询组件,所以URL.getPathURL.getFile应该返回相同的结果。 然而,select你需要的一个:文件的URL可能通常不具有查询组件,但我可以确定无论如何添加一个。

最后 – 也是最重要的 – 为什么我需要File对象; 为什么不是一个资源(URL)足够?

URL可能是不够的,因为文件可以让您访问pipe理数据,如权限(可读,可写,可执行),文件types(我是一个目录?),以及search和操作本地文件系统的能力。 如果这些是您需要的function,那么文件或path提供它们。

如果您有权访问Path,则不需要File。 但是,一些旧的API可能需要File。

(还有一个资源对象?)

不,没有。 有很多类似的命名,但它们不是ClassLoader.getResource意义上的资源。

Pavel Horal的答案很好。

正如他所说,“文件”一词在URL#getFilejava.io.File有完全不同(实际上不相关)的含义 – 可能是混淆的一部分。

只需添加:

  • Java中的资源是一个抽象的概念,可以被读取的数据源。 资源的位置(或地址)由Java对象用Java表示。

  • 资源可以对应于本地文件系统中的常规文件(具体来说,当其URLfile://开头时)。 但是一个资源是更普遍的(它也可以是一些文件存储在一个jar子里,或者一些数据从networking,或从内存中读取,或者…)。 而且它也更受限制,因为一个File (除了常规文件之外的其他内容:一个目录,一个链接)也可以被创build和写入。

  • 在Java中记住一个File对象并不真正代表“文件”,而是文件的位置(全名和path)。 所以,一个File对象允许你定位(和打开)一个文件,因为一个URL允许你访问(和打开)一个资源。 (Java中没有用于表示资源的Resource类,但是没有一个用于表示文件!一次: File不是文件,它是文件的path)。

据我了解,你可以将它们分类如下:

基于Web的:URI和URL。

  • url:一个url是一个明确的位置(只是一个普通的networking地址,如 – stackoverflow.com)
  • URI:永久URL是一个URI。 但是,URI也可以包含诸如“mailto:”之类的东西,所以它们也是我所说的一个“脚本”。

和本地:资源,path和文件

  • 资源:资源是你的jar里面的文件。 它们用来从jar /容器中加载文件。
  • path:path基本上是一个string。 但它带有一些方便的函数来连接多个string,或将文件添加到string。 它确保您正在build立的path是有效的。
  • 文件:这是对目录或文件的引用。 它用来修改文件,打开它们等

如果将他们合并成一个class级会更容易 – 他们确实很混乱:D

我希望这可以帮助你 :)

(我只是看看文档 – 看看docs.oracle.com)

文件是本地文件系统中实体的抽象表示。

path通常是指示文件系统内文件位置的string。 它通常不包含文件名。 所以c:\ documents \ mystuff \ stuff.txt将会有一个值为“C:\ documents \ mystuff”的path。显然绝对文件名和path的格式在文件系统和文件系统之间会有很大的不同。

URL是一个URI的可疑组合,URL通常代表通过http访问的资源。 我不认为有什么时候必须成为一个URI或一个URL的ironclad规则。 URI是“protocol:// resource-identifier”forms的string,比如bitcoin:// params, http ://something.com?param = value。 像URL这样的类通常包装string,并提供String没有理由提供的实用方法。

没有资源这样的东西,至less不是你说的意义上的。 仅仅因为一个名为getResource的方法并不意味着它返回一个Resourcetypes的对象。

最终找出类的方法的最好方法是在代码中创build它的一个实例,调用这些方法,然后在debugging模式下执行,或者将结果发送到System.out。