Java에서 상대 경로로 리소스 열기


84

Java 앱에서 파일과 디렉토리를 가져와야합니다.

다음은 프로그램 구조입니다.

./main.java
./package1/guiclass.java
./package1/resources/resourcesloader.java
./package1/resources/repository/modules/   -> this is the dir I need to get
./package1/resources/repository/SSL-Key/cert.jks    -> this is the file I need to get

guiclass 내 리소스 (디렉토리 및 파일)를로드 할 resourcesloader 클래스를로드합니다.

파일에 관해서는

resourcesloader.class.getClass().getResource("repository/SSL-Key/cert.jks").toString()

실제 경로를 얻으려면이 방법은 작동하지 않습니다.

디렉토리에 어떤 경로를 사용할지 모르겠습니다.


1
class.getClass ()는 class.getClassLoader ()와 동일하지 않습니다. 리소스와 동일한 패키지의 클래스를 사용하는 또 다른 솔루션 인 getResourceAsStream ()도 있습니다. 자세한 내용은 : tshikatshikaaa.blogspot.nl/2012/07/... .
Jérôme Verstrynge

답변:


48

로더를 가져 오는 클래스가 아니라 클래스 로더에 상대적인 경로를 제공하십시오. 예를 들면 :

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();

161

getClass().getResource("filename.txt")방법 을 사용하는 데 문제가있었습니다 . Java 문서 지침을 읽을 때 리소스가 리소스에 액세스하려는 클래스와 동일한 패키지에 있지 않은 경우로 시작하는 상대 경로를 제공해야합니다 '/'. 권장되는 전략은 리소스 파일을 루트 디렉터리의 "resources"폴더에 저장하는 것입니다. 예를 들어 구조가있는 경우 :

src/main/com/mycompany/myapp

그런 다음 maven이 권장하는대로 리소스 폴더를 추가 할 수 있습니다.

src/main/resources

또한 리소스 폴더에 하위 폴더를 추가 할 수 있습니다.

src/main/resources/textfiles

당신의 파일이라고 말할 myfile.txt당신이 그래서

src/main/resources/textfiles/myfile.txt

이제 여기에서 어리석은 경로 문제가 발생합니다.에 클래스가 있고 리소스 폴더에서 파일 com.mycompany.myapp package에 액세스하려고 한다고 가정 myfile.txt합니다. 일부는 다음을 제공해야한다고 말합니다.

"/main/resources/textfiles/myfile.txt" path

또는

"/resources/textfiles/myfile.txt"

둘 다 잘못되었습니다. 을 실행 mvn clean compile하면 파일과 폴더가 다음 위치에 복사됩니다.

myapp/target/classes 

폴더. 그러나 리소스 폴더는 거기에 있지 않고 리소스 폴더의 폴더 만 있습니다. 그래서 당신은 :

myapp/target/classes/textfiles/myfile.txt

myapp/target/classes/com/mycompany/myapp/*

따라서 getClass().getResource("")메서드 에 제공 할 올바른 경로 는 다음과 같습니다.

"/textfiles/myfile.txt"

여기있어:

getClass().getResource("/textfiles/myfile.txt")

더 이상 null을 반환하지 않지만 클래스를 반환합니다. 누군가에게 도움이되기를 바랍니다. "resources"폴더도 복사되지 않고 폴더에 직접 하위 폴더와 파일 만 있다는 것이 이상 "resources"합니다. "resources"폴더도 아래에서 찾을 수 있다는 것이 논리적으로 보입니다."myapp/target/classes"


1
내에서는 target/classes테스트 리소스가 아닌 기본 리소스 아래의 파일 만 볼 수 있습니다. 왜?
Ava

@Ava 테스트 폴더를 소스 폴더로 추가하면 좋습니다!
Aakash Parashar

@Ava, 답이 늦었지만 누군가를 도울 수 있습니다. Maven 수명주기mvn clean test-compile 이후 compile에 명령 을 실행해야합니다 . 생성됩니다 . target/test-classes
Alexander Radchenko

34

다른 사람들만큼 빨리 익히지 않는 사람들에게 추가 정보를 제공하기 위해 약간 다른 설정을 가지고있는 시나리오를 제공하고 싶습니다. 내 프로젝트는 다음 디렉터리 구조로 설정되었습니다 (Eclipse 사용).

계획/
  src / // 애플리케이션 소스 코드
    org /
      myproject /
        MyClass.java
  test / // 단위 테스트
  res / // 리소스
    images / // 아이콘 용 PNG 이미지
      my-image.png
    xml / // JAXB로 XML 파일의 유효성을 검사하기위한 XSD 파일
      my-schema.xsd
    conf / // Log4j 용 기본 .conf 파일
      log4j.conf
  lib / // 프로젝트 설정을 통해 빌드 경로에 추가 된 라이브러리

res 디렉토리 에서 내 리소스를로드하는 데 문제가있었습니다 . 모든 리소스를 소스 코드와 분리하기를 원했습니다 (간단히 관리 / 조직 목적). 그래서 내가해야 할 일은 res 디렉토리를 build-path 에 추가 한 다음 다음을 통해 리소스에 액세스하는 것입니다.

static final ClassLoader loader = MyClass.class.getClassLoader();

// in some function
loader.getResource("images/my-image.png");
loader.getResource("xml/my-schema.xsd");
loader.getResource("conf/log4j.conf");

참고 :/ 내가 사용하고 있기 때문에 리소스 문자열의 처음부터 생략 ClassLoader.getResource (문자열) 대신 Class.getResource (문자열) .


1
. + 1 ClassLoader 제안
pyb 2014

1
이 주제에 대한 최고의 답변! /리소스 경로의 시작 부분에서 사용하지 않는 것에 대한 팁 이 핵심이었습니다!
Kayhadrin 2016 년

10

Class에서 'getResource'를 사용하면 Class가 속한 패키지를 기준으로 상대 경로가 결정됩니다. ClassLoader에서 'getResource'를 사용하면 루트 폴더를 기준으로 상대 경로가 결정됩니다.

절대 경로를 사용하는 경우 두 'getResource'메소드가 모두 루트 폴더에서 시작됩니다.


효과를 잊지 마세요/
Gilberto

@nbeyer getResource절대 경로로 사용 하는 이유는 루트 폴더에서 시작합니까? 절대 경로의 목적은 아니다 절대 ?
atjua 2017-06-07

10

@GianCarlo : Java 프로젝트의 루트를 제공하는 시스템 속성 user.dir을 호출 한 다음이 경로를 상대 경로에 추가 할 수 있습니다. 예를 들면 다음과 같습니다.

String root = System.getProperty("user.dir");
String filepath = "/path/to/yourfile.txt"; // in case of Windows: "\\path \\to\\yourfile.txt
String abspath = root+filepath;



// using above path read your file into byte []
File file = new File(abspath);
FileInputStream fis = new FileInputStream(file);
byte []filebytes = new byte[(int)file.length()];
fis.read(filebytes);

1
OP는 클래스 경로에서 리소스를 찾고 싶었습니다 (대부분 빌드 중에 생성 된 jar에 있음). 이 방법은 목표를 달성하는 방법을 제공하지 않습니다. Filea를 jar 파일 내부의 리소스로 가리킬 수 없으며 파일 시스템의 적절한 항목 (예 : jar 자체) 만 가리킬 수 있습니다 .
Attila

원하는 경로를보기 위해 "user.dir"을 얻는 것이 좋습니다. 감사합니다
YouAreAwesome

5

eclipse + maven을 사용하는 사람들을 위해. 에서 파일 images/pic.jpg에 액세스하려고한다고 가정 해 보겠습니다 src/main/resources. 이 방법으로 수행 :

ClassLoader loader = MyClass.class.getClassLoader();
File file = new File(loader.getResource("images/pic.jpg").getFile());

완벽하게 정확하지만 널 포인터 예외가 발생할 수 있습니다. eclipse는 maven 디렉토리 구조의 폴더를 소스 폴더로 즉시 인식하지 못하는 것 같습니다. src/main/resources프로젝트의 소스 폴더 목록에서 폴더 를 제거하고 다시 넣어서 (프로젝트> 속성> 자바 빌드 경로> 소스> 폴더 제거 / 추가)이 문제를 해결할 수있었습니다.


2
resourcesloader.class.getClass()

다음과 같이 나눌 수 있습니다.

Class<resourcesloader> clazz = resourceloader.class;
Class<Class> classClass = clazz.getClass();

즉, 부트 스트랩 클래스를 사용하여 리소스를로드하려고합니다.

대신 다음과 같은 것을 원할 것입니다.

resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()

비 정적 컨텍스트에서 정적 메서드를 호출하는 것에 대해 javac 만 경고했다면 ...


1

다음 작업을합니까?

resourcesloader.class.getClass().getResource("/package1/resources/repository/SSL-Key/cert.jks")

패키지를 포함한 전체 경로를 지정할 수없는 이유가 있습니까?


1

위에서 언급 한 두 가지 답변으로 이동하십시오. 첫번째

resourcesloader.class.getClassLoader().getResource("package1/resources/repository/SSL-Key/cert.jks").toString();
resourcesloader.class.getResource("repository/SSL-Key/cert.jks").toString()

하나와 같은 것이되어야합니까?


1

파일의 실제 경로를 얻으려면 다음을 시도하십시오.

URL fileUrl = Resourceloader.class.getResource("resources/repository/SSL-Key/cert.jks");
String pathToClass = fileUrl.getPath;    

Resourceloader는 여기에서 클래스 이름입니다. "resources / repository / SSL-Key / cert.jks"는 파일의 상대 경로입니다. 나머지 폴더 구조가 남아있는 ./package1/java에 guiclass가있는 경우 상대 경로를 정의하는 규칙 때문에 "../resources/repository/SSL-Key/cert.jks"를 상대 경로로 사용합니다.

이렇게하면 BufferedReader로 파일을 읽을 수 있습니다. 파일 경로를 식별하는 데 문자열을 사용하지 마십시오. 경로에 영어 알파벳이 아닌 공백이나 일부 문자가 있으면 문제가 발생하고 파일을 찾을 수 없습니다.

BufferedReader bufferedReader = new BufferedReader(
                        new InputStreamReader(fileUrl.openStream()));

0

.getFile()null 포인터 예외를 방지하고 데이터 디렉토리에 대한 경로를 설정하기 위해 @ jonathan.cone의 한 라이너 ( )를 약간 수정했습니다 . 나를 위해 일한 것은 다음과 같습니다.

String realmID = new java.util.Scanner(new java.io.File(RandomDataGenerator.class.getClassLoader().getResource("data/aa-qa-id.csv").getFile().toString())).next();

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.