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中的URI和URL之间的区别是前者不编码空格吗? 参看 在Java中冲突的文件,URI和URL (这个答案很好地解释了两个术语之间的一般概念上的区别: URI标识和URL定位 )
最后 – 也是最重要的 – 为什么我需要File
对象; 为什么不是一个资源( URL
)足够? (还有一个资源对象?)
对不起,如果这个问题有点没有组织; 它只是反映了我的困惑… 🙂
UPDATE 2017-04-12检查JvR的答案,因为它包含更详尽和精确的解释!
请注意,我不认为自己有100%的能力回答,但是这里有一些评论:
-
File
表示可通过文件系统访问的文件或目录 - 资源是可由应用程序加载的数据对象的通用术语
- 通常资源是与应用程序/库一起分发的文件,并通过类加载机制加载(当它们驻留在类path中时)
-
URL#getPath
是URL#getPath
path部分的getter(protocol://host/path?query
) - 根据JavaDoc的
URL#getFile
返回path+query
在Java中, URI
只是一个操作通用标识符本身的数据结构。
另一方面, URL
实际上是一个资源定位器,并提供了通过注册的URLStreamHandler
实际读取资源的function。
URL可以导致文件系统资源,您可以使用file://
protocol(因此File
< – > URL
关系)构造每个文件系统资源的URL
。
另请注意,该URL#getFile
与java.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.getPath
和URL.getFile
应该返回相同的结果。 然而,select你需要的一个:文件的URL可能通常不具有查询组件,但我可以确定无论如何添加一个。
最后 – 也是最重要的 – 为什么我需要File对象; 为什么不是一个资源(URL)足够?
URL可能是不够的,因为文件可以让您访问pipe理数据,如权限(可读,可写,可执行),文件types(我是一个目录?),以及search和操作本地文件系统的能力。 如果这些是您需要的function,那么文件或path提供它们。
如果您有权访问Path,则不需要File。 但是,一些旧的API可能需要File。
(还有一个资源对象?)
不,没有。 有很多类似的命名,但它们不是ClassLoader.getResource
意义上的资源。
Pavel Horal的答案很好。
正如他所说,“文件”一词在URL#getFile
和java.io.File
有完全不同(实际上不相关)的含义 – 可能是混淆的一部分。
只需添加:
-
Java中的资源是一个抽象的概念,可以被读取的数据源。 资源的位置(或地址)由Java对象用Java表示。
-
资源可以对应于本地文件系统中的常规文件(具体来说,当其
URL
以file://
开头时)。 但是一个资源是更普遍的(它也可以是一些文件存储在一个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。