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


96

我现在正在看一段Java代码,它采用路径作为String并使用来获取其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()有什么区别?(有趣的是,它们似乎都返回字符串,这可能使我的思想状态大增……)

现在,如果我有一个引用jar文件中的类或包的定位器,这两个(即文件字符串的路径)是否会有所不同?

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

JavaURIURL 之间的区别是前者不对空格进行编码吗?cf. Java中的文件,URI和URL发生冲突(此答案很好地解释了这两个术语之间的一般性概念上的区别:URI标识和URL定位;

最后,也是最重要的是,为什么我需要File对象?为什么资源(URL)不够?(并且有一个Resource对象吗?)

抱歉,这个问题有点混乱。它只是反映了我的困惑... :)


5
而且您甚至还没有开始Path从NIO看文件系统:)
eckes

2
@eckes请一次头痛一次。;)
基督教徒

1
那么在您的问题的上下文文件/ URL + URI是不相关的。一个是命名和操作文件的手段,另一个是命名和读取资源(可以是文件)的方法。getFile和getPath方法处理URL的组件,这些组件(容易混淆)被命名为文件对象。类加载器资源不能表示为文件,因为它们可以具有不同的来源(或嵌套在JAR文件中)。
eckes

1
我会指出,此代码不太可能按预期工作。A URL不透明的 -如您所显示的jar:file:,即.jar存档中的资源。将其打包为a File几乎不会产生任何有用的结果。
蜘蛛鲍里斯(Boris the Spider)

1
问题的核心在于,取决于上下文,资源路径一词可能具有不同的含义。
2015年

Answers:


43

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


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

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

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

URL另一方面,它实际上是资源定位器,它为您提供了一些功能,可以通过注册URLStreamHandlers 实际读取资源。

URL可以导致文件系统资源,并且您可以使用file://协议为每个文件系统资源构造URL (因此为File<-> URL关系)。

另请注意,这URL#getFile与无关java.io.File


为什么需要File对象?为什么资源(URL)不够?

够了 仅当您要将资源传递给只能使用文件的某些组件时,才需要从中获取资源File。但是,并非所有资源URL都可以转换为File

还有资源对象吗?

从JRE的角度来看,这只是一个术语。一些框架为您提供了此类(例如Spring的Resource)。


5
也有java.nio.file.Path,它基本上是(Java 7+)的替代品java.io.File,因为在Java的早期,显然不太考虑使用后者的API。
ntoskrnl 2015年

1
通常,除非绝对需要,否则应尽量减少URL的使用。原因是URL的equalshashCode方法以令人惊讶的方式实现:它们阻止了方法调用。
kibibyte

3
@kibibyte:我希望该调用能够阻塞,具有哈希码的异步实现,并且现在等于该值将非常令人不安。我认为您的意思是,这些呼叫将尝试并解析主机以查找它们是否等效,从而可能造成阻塞的网络呼叫。
Newtopian '16

52

我现在很困惑-我猜主要是因为术语。有人可以请我介绍这些差异,还是提供一些指向虚拟模型的材料的链接?尤其是URL的URI和文件的资源?对我来说,感觉它们应该分别是同一回事...

该术语令人困惑,有时甚至令人困惑,并且主要源于Java作为API和平台的发展。要了解这些术语如何表示它们的作用,重要的是要认识到影响Java设计的两件事:

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

我将逐步介绍这些概念以及它们的产生方式。在那之后,我将回答您的其他特定问题,因为在第一部分中我可能不得不提及某些内容。

什么是“资源”?

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

由于Java的早期设计目标之一是在浏览器内部运行,因此它是具有非常有限的权限/特权/安全清除的沙盒应用程序(小程序!),因此Java在文件(某些内容在本地)上产生了明显的(理论上的)区别。文件系统)和资源(需要读取的内容)。 这就是为什么通过ClassLoader.getResource而不是通过File类来完成与应用程序相关的某些内容(图标,类文件等)的读取的原因。

不幸的是,由于“资源” 此解释之外也是一个有用的通用术语,因此它也用于命名非常具体的事物(例如,类ResourceBundleUIResourceResource),在这种意义上,它们不是资源。

表示资源(通往资源的路径)的主要类是java.nio.file.Pathjava.io.Filejava.net.URIjava.net.URL

文件(java.io,1.0)

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

File类表示可通过平台的本机文件系统访问的资源。它仅包含文件名,因此它实际上是主机平台根据其自身的设置,规则和语法解释的路径(请参阅下文)。

请注意,File不需要指向本地内容,而仅指向主机平台在文件访问上下文中可以理解的内容,例如Windows中的UNC路径。如果您在操作系统中将ZIP文件作为文件系统挂载,则File会很好地读取其包含的条目。

URL(java.net,1.0)

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

与资源的概念一致,URL表示该资源的方式与File类表示主机平台中文件的方式相同:作为指向资源的结构化字符串。 URL还包含一种方案,该方案提示如何访问资源(“ file:”为“询问主机平台”),因此允许通过HTTP,FTP,JAR内以及诸如此类来指向资源。

不幸的是,URL带有自己的语法和术语,包括“文件”和“路径”的使用。如果URL是文件URL,则URL.getFile将返回与引用文件的路径字符串相同的字符串。

Class.getResource 返回一个URL:它比返回File更灵活,并且可以满足1990年代初期系统的需求。

URI(java.net,1.4)

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

URI是URL上的(轻微)抽象。 URI和URL之间的区别是概念性的,并且大多是学术性的,但是URI在形式上更好地定义,并且涵盖了更广泛的用例。由于URL和URI是不同的,因此引入了一个新类来表示它们,并使用URI.toURL和URL.toURI方法在彼此之间移动。

在Java中,URL和URI之间的主要区别在于URL 带有可解析的期望,这是应用程序可能需要InputStream的东西;URI更像是一个抽象的东西,它可能指向可解决的东西(通常是这样做的),但是它的含义和实现方式更容易受到上下文和解释的影响。

路径(java.nio.file,1.7)

可用于在文件系统中定位文件的对象。它通常代表系统相关的文件路径。

在Path界面中图标化的新文件API提供了比File类所提供的更大的灵活性。Path接口是File类抽象,并且是New IO File API的一部分。如主机平台所理解的,File必须指向“文件”,而Path更通用:它表示任意文件系统中的文件(资源)。

Path消除了对主机平台文件概念的依赖。它可以是ZIP文件中的条目,可以通过FTP或SSH-FS访问的文件,应用程序类路径的多根表示形式,或者实际上可以通过FileSystem接口及其驱动程序FileSystemProvider有意义地表示的任何内容。它将“挂载”文件系统的功能带入Java应用程序的上下文中。

主机平台通过“默认文件系统”表示;调用时File.toPath,您会在默认文件系统上获得一个路径。


现在,如果我有一个引用jar文件中的类或包的定位器,这两个(即文件字符串的路径)是否会有所不同?

不太可能。如果jar文件是本地文件系统上,你不应该有一个查询组件,所以URL.getPathURL.getFile应该返回相同的结果。但是,请选择一个您需要的文件:文件URL通常可能没有查询组件,但是无论如何我肯定可以添加一个。

最后-最重要的是-为什么我需要File对象;为什么资源(URL)不够?

URL可能不够用,因为File使您可以访问内部管理数据,例如权限(可读,可写,可执行),文件类型(我是目录吗?)以及搜索和操作本地文件系统的能力。如果您需要这些功能,则文件或路径将提供它们。

如果可以访问Path,则不需要File。不过,某些较旧的API可能需要文件。

(并且有一个Resource对象吗?)

不,没有。有很多类似的名称,但是它们并不是的资源ClassLoader.getResource


哇,非常彻底。只是经过它,但是已经有了第一个后续问题:当您说一个文件“仅包含文件名”时,您是否与它的最初声明“文件和目录路径名的抽象表示”相矛盾? -还有吗?
基督教徒

1
@Christian我的意思是“仅名称”,例如:不会以任何方式为文件的内容建模;它只是一根细绳子。API文档引用了“抽象表示”部分。;)
JvR

这个答案值得更多的赞扬...将更新我接受的答案,以使读者知道这个答案。
帕维尔·霍拉尔

12

帕维尔·霍拉尔(Pavel Horal)的回答很好。

正如他所说,“文件”一词在URL#getFilevs中的 含义完全不同(实际上是不相关的),这java.io.File可能是造成混淆的部分原因。

只需添加:

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

  • 一个 资源可以对应于一个普通文件在本地文件系统(具体而言,当其URL开始file://)。但是资源更通用(它也可以是存储在jar中的某些文件,或者可以从网络,内存或其他要读取的数据)。而且它也有更多限制,因为File还可以创建a (除了常规文件以外的其他东西:目录,链接)。

  • 请记住,在Java中,File对象实际上并不代表“文件”,而是文件的位置(全名,带路径)。所以,一个File对象允许您定位(和打开)文件,因为对象可以URL访问(并打开)资源。(ResourceJava中没有类可以代表资源,但是也没有一个类可以代表文件!再次:File不是文件,它是文件的路径)。


3

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

基于Web:URI和URL。

  • URL:URL是internt上的确定位置(只是一个普通的Web地址,例如-stackoverflow.com)
  • URI:Ever URL是URI。但是URI也可以包含“ mailto:”之类的内容,因此,它们也可以说是“脚本”。

和本地:资源,路径和文件

  • 资源:资源是jar中的文件。它们用于从jar /容器中加载文件。
  • 路径:路径基本上是一个字符串。但是它带有一些方便的函数来连接多个字符串,或将文件添加到字符串。它确保您正在构建的路径是有效的。
  • 文件:这是对目录或文件的引用。它用于修改文件,打开文件等。

如果将它们合并到一个类中会更容易-它们确实令人困惑:D

我希望这可以帮助你 :)

(我只是看了一下文档-看docs.oracle.com)


0

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

路径通常是一个字符串,指示文件在文件系统中的位置。它通常不包含文件名。因此,c:\ documents \ mystuff \ stuff.txt的路径值为“ C:\ documents \ mystuff”。显然,每个文件系统的绝对文件名和路径的格式差异很大。

URL是URI的缩写,URL通常代表可通过http访问的资源。我认为什么时候必须是URI还是URL并没有任何铁定的规则。URI是“ protocol:// resource-identifier”形式的字符串,例如bitcoin:// params,http://something.com?param = value 。像URL这样的类通常包装字符串并提供String不需要提供的实用程序方法。

没有诸如资源之类的东西,至少在您所说的意义上没有。仅仅因为一个名为getResource的方法并不意味着它返回Resource类型的对象。

最终,弄清楚Class方法的作用的最佳方法是在代码中创建它的实例,调用方法,然后以调试模式逐步执行或将结果发送到System.out。


您对“路径”的定义与OP上下文中的“路径”概念
不符
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.