Java에서 리소스를로드하는 가장 좋은 방법을 알고 싶습니다.
this.getClass().getResource() (or getResourceAsStream())
,Thread.currentThread().getContextClassLoader().getResource(name)
,System.class.getResource(name)
.
Java에서 리소스를로드하는 가장 좋은 방법을 알고 싶습니다.
this.getClass().getResource() (or getResourceAsStream())
,Thread.currentThread().getContextClassLoader().getResource(name)
,System.class.getResource(name)
.답변:
원하는대로 솔루션을 찾으십시오 ...
호출되는 클래스에서 getResource
/ getResourceAsStream()
얻을 두 가지가 있습니다 ...
그래서 만약 당신이
this.getClass().getResource("foo.txt");
"this"클래스와 동일한 패키지에서 "this"클래스의 클래스 로더를 사용하여 foo.txt를로드하려고 시도합니다. "/"를 앞에 넣으면 절대적으로 리소스를 참조하는 것입니다.
this.getClass().getResource("/x/y/z/foo.txt")
"this"의 클래스 로더와 xyz 패키지에서 리소스를로드합니다 (해당 패키지의 클래스와 동일한 디렉토리에 있어야 함).
Thread.currentThread().getContextClassLoader().getResource(name)
컨텍스트 클래스 로더와 함께로드되지만 패키지에 따라 이름을 확인하지 않습니다 (절대적으로 참조되어야 함).
System.class.getResource(name)
시스템 클래스 로더로 리소스를로드합니다 (java.lang 패키지 (System의 패키지)에 아무것도 넣을 수 없기 때문에 절대적으로 참조되어야합니다.
소스를 살펴보십시오. 또한 getResourceAsStream이 getResource에서 반환 된 URL에서 "openStream"을 호출하고이를 반환 함을 나타냅니다.
Thread#setContextClassLoader
입니다. 프로그램이 실행되는 동안 클래스 경로를 수정해야하는 경우 유용합니다.
글쎄, 그것은 부분적으로 당신이 실제로 파생 클래스에 있다면 어떤 일이 일어나기를 원하는지에 달려 있습니다 .
예를 들어, 가정하자가 SuperClass
에 a.jar에 있으며 SubClass
b.JAR가에, 당신은 인스턴스 메서드에 코드를 실행을하는지에 선언 SuperClass
했지만 곳은 this
의 인스턴스를 참조 SubClass
. 사용 this.getClass().getResource()
하면 SubClass
B.jar에서에 상대적으로 보입니다. 나는 그것이 일반적으로 필요한 것이 아니라고 생각합니다.
개인적으로 저는 아마도 Foo.class.getResourceAsStream(name)
가장 자주 사용할 것입니다. 당신이 쫓고있는 리소스의 이름을 이미 알고 있고 그것이 상대적인 위치를 확신 Foo
한다면 그것이 IMO를 수행하는 가장 강력한 방법입니다.
물론 그것이 당신이 원하는 것이 아닐 때도 있습니다. 각 사건의 장점을 판단하십시오. "이 리소스가이 클래스에 번들로 제공된다는 것을 알고 있습니다."가 가장 일반적인 것입니다.
this.getClass()
. 하위 클래스의 인스턴스를 만들고 메서드를 호출합니다. 슈퍼 클래스가 아닌 하위 클래스의 이름이 출력됩니다.
아래와 같이 세 곳을 검색합니다. 의견을 환영합니다.
public URL getResource(String resource){
URL url ;
//Try with the Thread Context Loader.
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
if(classLoader != null){
url = classLoader.getResource(resource);
if(url != null){
return url;
}
}
//Let's now try with the classloader that loaded this class.
classLoader = Loader.class.getClassLoader();
if(classLoader != null){
url = classLoader.getResource(resource);
if(url != null){
return url;
}
}
//Last ditch attempt. Get the resource from the classpath.
return ClassLoader.getSystemResource(resource);
}
나는 다른 답변이 정말 늦었다는 것을 알고 있지만 마지막에 도움이 된 것을 공유하고 싶었습니다. 또한 파일 시스템의 절대 경로 (클래스 경로뿐만 아니라)에서 리소스 / 파일을로드합니다.
public class ResourceLoader {
public static URL getResource(String resource) {
final List<ClassLoader> classLoaders = new ArrayList<ClassLoader>();
classLoaders.add(Thread.currentThread().getContextClassLoader());
classLoaders.add(ResourceLoader.class.getClassLoader());
for (ClassLoader classLoader : classLoaders) {
final URL url = getResourceWith(classLoader, resource);
if (url != null) {
return url;
}
}
final URL systemResource = ClassLoader.getSystemResource(resource);
if (systemResource != null) {
return systemResource;
} else {
try {
return new File(resource).toURI().toURL();
} catch (MalformedURLException e) {
return null;
}
}
}
private static URL getResourceWith(ClassLoader classLoader, String resource) {
if (classLoader != null) {
return classLoader.getResource(resource);
}
return null;
}
}
위에서 제안한 많은 방법과 기능을 시도했지만 내 프로젝트에서 작동하지 않았습니다. 어쨌든 나는 해결책을 찾았으며 여기에 있습니다.
try {
InputStream path = this.getClass().getClassLoader().getResourceAsStream("img/left-hand.png");
img = ImageIO.read(path);
} catch (IOException e) {
e.printStackTrace();
}
this.getClass().getResourceAsStream()
이 경우 더 잘 사용해야 합니다. getResourceAsStream
메서드 의 소스를 살펴보면 여러분과 동일한 일을하지만 더 현명한 방식으로 수행 ClassLoader
된다는 것을 알 수 있습니다 (클래스에서 찾을 수 없는 경우 대체 ). 또한 코드에서 잠재력 null
을 만날 수 있음을 나타냅니다 getClassLoader
…
this.getClass().getResourceAsStream()
이 나를 위해 작동하지 않으므로 그 작동을 사용합니다. 저와 같은 문제에 직면 할 수있는 사람들이 있다고 생각합니다.