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().

저는 지금 완전히 혼란 스럽습니다. 대부분 용어 때문에 그렇습니다. 누군가 저에게 차이점을 안내하거나 더미 방지 자료에 대한 몇 가지 링크를 제공 할 수 있습니까? 특히 URI to URL 및 Resource to File ? 제게는 각각 똑같아 야 할 것 같아요 ...

차이점 getFile() 와는 getPath()여기에 설명 : url.getFile ()와 getpath ()의 차이점은 무엇입니까? (흥미롭게도 둘 다 Strings를 반환하는 것처럼 보이며 아마도 내 마음 상태에 많은 것을 추가 할 것입니다 ...)

이제 jar 파일의 클래스 또는 패키지를 참조하는 로케이터가있는 경우이 두 가지 (예 : 파일 문자열 경로)가 다를까요?

resource.toString()jar:file:/C:/path/to/my.jar!/com/example/결국 당신에게 줄 것입니다 (느낌표에 유의하십시오).

Java에서 URIURL 의 차이점 은 전자가 공백을 인코딩하지 않습니까? Cf. Java에서 충돌하는 파일, URI 및 URL (이 답변은 일반적이고 개념적인 상당히 잘 두 용어의 차이를 : URI를 확인하고 URL을 찾을; )

마지막으로, 가장 중요한 것은 File객체 가 필요한 가요? 리소스가 아닌 이유 (URL )가 충분 무엇입니까? (그리고 Resource 객체가 있습니까?)

이 질문이 약간 정리되지 않은 경우 죄송합니다. 그것은 단지 내가 가진 혼란을 반영합니다 ... :)


5
그리고 PathNIO의 FileSystem 을보기 시작하지도 않았습니다. :)
eckes

2
@eckes 한 번에 하나의 두통을주세요. ;)
Christian

1
질문의 맥락에서 File / URL + URI는 관련이 없습니다. 하나는 파일에 이름을 지정하고 작동하는 수단이고 다른 하나는 리소스 (파일 일 수 있음)에서 이름을 지정하고 읽는 방법입니다. getFile 및 getPath 메소드는 파일 객체와 같이 (혼란스럽게도) 이름이 지정된 URL의 구성 요소를 처리합니다. 클래스 로더 자원은 출처가 다르거 나 JAR 파일에 중첩 될 수 있으므로 파일로 표시되지 않습니다.
eckes

1
이 코드는 의도 한대로 작동하지 않을 것입니다. A URL불투명 합니다 jar:file:. 즉, .jar아카이브 의 리소스입니다 . 그것을 a에 넣는 File것은 유용한 결과를 가져올 가능성이 거의 없습니다.
보리스 스파이더

1
문제의 핵심은 리소스경로 라는 단어 가 문맥에 따라 다른 의미를 가질 수 있다는 것입니다.
Raedwald

답변:


43

업데이트 2017-04-12 JvR의 답변 에 더 철저하고 정확한 설명이 포함되어 있으므로 확인하십시오 !


내가 100 % 대답 할 능력이 있다고 생각하지는 않지만, 그럼에도 불구하고 여기에 몇 가지 의견이 있습니다.

  • File 파일 시스템을 통해 액세스 할 수있는 파일 또는 디렉토리를 나타냅니다.
  • 리소스 는 응용 프로그램에서로드 할 수있는 데이터 개체에 대한 일반적인 용어 입니다.
    • 일반적으로 리소스 는 응용 프로그램 / 라이브러리와 함께 배포되고 클래스 로딩 메커니즘을 통해로드되는 파일입니다 (클래스 경로에있을 때).
  • URL#getPathURL ( protocol://host/path?query) 의 경로 부분에있는 게터입니다.
  • URL#getFile JavaDoc 반환에 따라 path+query

Java에서는 URI일반 식별자 자체를 조작하기위한 데이터 구조 일뿐입니다.

URL반면에 실제로 리소스 로케이터이며 등록 된 URLStreamHandlers 를 통해 실제로 리소스를 읽을 수있는 기능을 제공합니다 .

URL은 파일 시스템 리소스로 이어질 수 있으며 file://프로토콜 (따라서 File<-> URL관계) 을 사용하여 모든 파일 시스템 리소스에 대한 URL을 구성 할 수 있습니다 .

또한 그 점에 유의 URL#getFile관련이 없습니다 java.io.File.


왜 파일 객체가 필요합니까? 리소스 (URL)가 충분하지 않은 이유는 무엇입니까?

충분합니다. 파일로만 작동 할 수있는 일부 구성 요소에 리소스를 전달하려는 경우에만 리소스를 가져와야 File합니다. 그러나 모든 리소스 URL을로 변환 할 수있는 것은 아닙니다 File.

그리고 Resource 객체가 있습니까?

JRE 관점에서 이것은 단지 용어 일뿐입니다. 일부 프레임 워크는 이러한 클래스를 제공합니다 (예 : Spring의 Resource ).


5
또한 java.nio.file.Path기본적으로를 대체하는 (Java 7+) java.io.File도 있습니다. 후자의 API는 Java 초기에 제대로 고려되지 않았기 때문입니다.
ntoskrnl

1
일반적으로 절대적으로 필요한 경우가 아니면 URL 사용을 최소화해야합니다. 그 이유는 URL의 것입니다 등호해시 코드의 가 메서드 호출을 차단 : 방법은 놀라운 방식으로 구현된다.
kibibyte

3
@kibibyte : 호출이 차단되고 해시 코드의 비동기 구현이 있고 지금은 매우 불안정 할 것으로 예상합니다. 당신이 의미하는 바는 호출이 호스트가 동등한 지 확인하기 위해 시도하고 해결하여 잠재적으로 네트워크 호출을 차단할 수 있다는 것입니다.
Newtopian

52

저는 지금 완전히 혼란 스럽습니다. 대부분 용어 때문에 그렇습니다. 누군가 저에게 차이점을 안내하거나 더미 방지 자료에 대한 몇 가지 링크를 제공 할 수 있습니까? 특히 URI to URL 및 Resource to File? 제게는 각각 똑같아 야 할 것 같아요 ...

용어는 혼란스럽고 때로는 혼란스럽고 대부분 시간이 지남에 따라 API와 플랫폼으로 Java의 진화에서 탄생했습니다. 이러한 용어가 의미하는 방식을 이해하려면 Java의 디자인에 영향을 미치는 두 가지 사항을 인식하는 것이 중요합니다.

  • 이전 버전과의 호환성. 이전 애플리케이션은 이상적으로 수정없이 최신 설치에서 실행되어야합니다. 이는 이전 API (이름 및 용어 포함)를 모든 최신 버전에서 유지 관리해야 함을 의미합니다.
  • 크로스 플랫폼. API는 운영 체제 든 브라우저 든 기본 플랫폼의 사용 가능한 추상화를 제공해야합니다.

개념과 그 결과를 살펴 보겠습니다. 그 후에 다른 구체적인 질문에 답하겠습니다. 첫 번째 부분에서 무언가를 참조해야 할 수도 있기 때문입니다.

"자원"이란 무엇입니까?

찾아서 읽을 수있는 추상적이고 일반적인 데이터입니다. 간단히 말해서, Java는 이것을 사용하여 파일이 아닐 수 있지만 명명 된 데이터 조각을 나타내는 "파일"을 참조합니다. Java에서 직접 클래스 또는 인터페이스 표현이 없지만 속성 (위치 찾기, 읽기 가능)으로 인해 종종 URL로 표현됩니다.

Java의 초기 디자인 목표 중 하나는 브라우저 내에서 실행되는 것이었기 때문에 권한 / 권한 / 보안 허가가 매우 제한된 샌드 박스 애플리케이션 (애플릿!)으로 Java는 파일 (로컬에있는 것)간에 명확한 (이론적) 차이를 만듭니다. 파일 시스템) 및 리소스 (읽어야하는 것). 이것이 애플리케이션 (아이콘, 클래스 파일 등)과 관련된 무언가를 읽는 것이 ClassLoader.getResourceFile 클래스를 통하지 않고 수행하는 이유입니다.

안타깝게도 "자원" 은이 해석 이외 의 유용한 일반 용어이기도하므로 자원 이 아닌 매우 구체적인 항목 (예 : ResourceBundle , UIResource , Resource )의 이름을 지정하는데도 사용됩니다 .

리소스 (경로)를 나타내는 기본 클래스는 java.nio.file.Path , java.io.File , java.net.URIjava.net.URL 입니다.

파일 (java.io, 1.0)

파일 및 디렉토리 경로 이름의 추상적 인 표현입니다.

File 클래스는 플랫폼의 기본 파일 시스템을 통해 도달 할 수 있는 리소스를 나타냅니다 . 파일의 이름 만 포함하므로 호스트 플랫폼이 자체 설정, 규칙 및 구문에 따라 해석하는 경로 (나중 참조)에 가깝습니다.

File은 로컬 을 가리킬 필요가 없으며 호스트 플랫폼이 파일 액세스의 맥락에서 이해하는 것 (예 : Windows의 UNC 경로) 을 가리킬 필요가 없습니다 . OS에서 ZIP 파일을 파일 시스템으로 마운트하면 File은 포함 된 항목을 정상적으로 읽습니다.

URL (java.net, 1.0)

클래스 URL은 World Wide Web의 "자원"에 대한 포인터 인 Uniform Resource Locator를 나타냅니다. 리소스는 파일이나 디렉토리와 같은 단순한 것일 수도 있고 데이터베이스 또는 검색 엔진에 대한 쿼리와 같이 더 복잡한 개체에 대한 참조 일 수도 있습니다.

리소스 개념과 함께 URL은 File 클래스가 호스트 플랫폼에서 파일을 나타내는 것과 동일한 방식으로 리소스를 나타내는 구조화 된 문자열로 해당 리소스를 나타냅니다. URL은 또한 리소스에 도달하는 방법 ( "file :"이 "호스트 플랫폼에 요청")에 대한 힌트를 포함하므로 HTTP, FTP, JAR 내부 등을 통해 리소스를 가리킬 수 있습니다.

안타깝게도 URL에는 "파일"및 "경로"사용을 포함하여 자체 구문과 용어가 함께 제공됩니다. URL이 파일 URL 인 경우 URL.getFile은 참조 된 파일의 경로 문자열과 동일한 문자열을 반환합니다.

Class.getResource URL을 반환합니다 : 파일을 반환하는 것보다 더 유연하며 1990 년대 초에 상상했던 시스템의 요구를 충족 시켰습니다.

URI (java.net, 1.4)

URI (Uniform Resource Identifier) ​​참조를 나타냅니다.

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)가 충분하지 않은 이유는 무엇입니까?

File은 권한 (읽기, 쓰기 가능, 실행 가능), 파일 유형 (나는 디렉토리입니까?) 및 로컬 파일 시스템을 검색하고 조작하는 기능과 같은 하우스 키핑 데이터에 대한 액세스를 제공하기 때문에 URL이 충분하지 않을 수 있습니다. 이러한 기능이 필요한 경우 파일 또는 경로에서 제공합니다.

Path에 대한 액세스 권한이 있으면 File이 필요하지 않습니다. 하지만 일부 오래된 API에는 파일이 필요할 수 있습니다.

(그리고 Resource 객체가 있습니까?)

아니, 없습니다. 이와 같은 이름이 많은 것들이 있지만 ClassLoader.getResource.


와, 아주 철저합니다. 그냥 살펴 보지만 이미 첫 번째 후속 질문이 있습니다. 파일이 "파일 이름 만 포함"이라고 말할 때 "파일 및 디렉토리 경로 이름의 추상적 인 표현"이라는 초기 진술과 모순되지 마십시오. -iemore?
Christian

1
@Christian 나는 다음과 같이 "이름 만"을 의미했습니다. 어떤 식 으로든 파일의 내용을 모델링하지 않습니다. 그것은 단지 끈을 둘러싼 얇은 포장지 일뿐입니다. "추상 표현"부분은 API 문서에서 인용되었습니다. ;)
JvR 2016

이 답변은 훨씬 더 많은 찬성 투표를 할 가치가 있습니다 ...이 답변을 독자에게 알리기 위해 수락 된 답변을 업데이트합니다.
Pavel Horal

12

Pavel Horal의 대답 은 좋습니다.

그가 말했듯이, 단어 "파일"에서 완전히 다른 (실질적으로 관련이없는)의 의미가 URL#getFile대를 java.io.File- 할 수 혼란의 일부입니다.

추가하기 :

  • Java 의 리소스 는 읽을 수있는 데이터 소스 인 추상 개념입니다. 자원의 위치 (또는 주소)는 Java에서 URL객체로 표시됩니다.

  • 리소스 (그 때, 즉 로컬 파일 시스템에 일반 파일에 대응할 수 URL시작 file://). 그러나 리소스는 더 일반적입니다 (항아리에 저장된 일부 파일이거나 네트워크 또는 메모리에서 읽을 데이터 일 수도 있습니다.). 또한 File(일반 파일이 아닌 다른 것 : 디렉토리, 링크) 생성 및 쓰기가 가능 하기 때문에 더 제한적 입니다.

  • Java에서 File객체는 실제로 "파일"이 아니라 파일의 위치 (경로가있는 전체 이름)를 나타냅니다. 따라서 File개체를 사용하면 URL리소스에 액세스하고 열 수 있으므로 파일을 찾고 열 수 있습니다. ( Resource자바에는 리소스를 나타내는 클래스 가 없지만 파일 을 나타내는 클래스 는 없습니다 ! 한 번 더 : File파일이 아니라 파일의 경로입니다).


3

내가 이해 한대로 다음과 같이 분류 할 수 있습니다.

웹 기반 : URI 및 URL.

  • URL : URL은 internt의 명확한 위치입니다 (예 : stackoverflow.com과 같은 일반적인 웹 주소).
  • URI : Ever URL은 URI입니다. 그러나 URI는 "mailto :"와 같은 것을 포함 할 수도 있습니다. 그래서 그들은 또한 제가 말하고 싶은 "스크립트"의 일부입니다.

및 로컬 : 리소스, 경로 및 파일

  • 리소스 : 리소스는 항아리 안에있는 파일입니다. jar / 컨테이너에서 파일을로드하는 데 사용됩니다.
  • 경로 : 경로는 기본적으로 문자열입니다. 그러나 여러 문자열을 연결하거나 파일을 문자열에 추가하는 몇 가지 편리한 기능이 제공됩니다. 빌드중인 경로가 유효한지 확인합니다.
  • 파일 : 디렉토리 또는 파일에 대한 참조입니다. 파일 수정, 열기 등에 사용됩니다.

그들이 하나의 클래스로 병합되면 더 쉬울 것입니다-정말 혼란 스럽습니다 : D

도움이 되었기를 바랍니다. :)

(방금 문서를 보았습니다-docs.oracle.com 참조)


0

파일은 로컬 파일 시스템에있는 엔티티의 추상적 인 표현입니다.

경로는 일반적으로 파일 시스템 내의 파일 위치를 나타내는 문자열입니다. 일반적으로 파일 이름은 포함되지 않습니다. 따라서 c : \ documents \ mystuff \ stuff.txt는 값이 "C : \ documents \ mystuff"인 경로를 갖게됩니다. 분명히 절대 파일 이름 및 경로의 형식은 파일 시스템마다 크게 다릅니다.

URL은 일반적으로 http를 통해 액세스 할 수있는 리소스를 나타내는 URL이있는 URI의 susbset입니다. 어떤 것이 URI와 URL이되어야 할 때 어떤 종류의 철칙이 있다고 생각하지 않습니다. URI는 bitcoin : // params, http://something.com?param=value 와 같은 "protocol : // resource-identifier"형식의 문자열입니다 . URL과 같은 클래스는 일반적으로 문자열을 래핑하고 String이 제공 할 이유가없는 유틸리티 메서드를 제공합니다.

최소한 당신이 말하는 의미에서는 자원과 같은 것은 없습니다. 메소드 이름이 getResource라고해서 Resource 유형의 객체를 반환한다는 의미는 아닙니다.

궁극적으로 클래스의 메서드가 수행하는 작업을 파악하는 가장 좋은 방법은 코드에서 해당 인스턴스를 만들고 메서드를 호출 한 다음 디버그 모드에서 단계를 수행하거나 결과를 System.out에 보내는 것입니다.


"경로"에 대한 정의가 OP 컨텍스트의 "경로"개념과 일치하지 않습니다
leonbloy
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.