리소스 폴더에서 파일을 어떻게로드합니까?


240

내 프로젝트의 구조는 다음과 같습니다.

/src/main/java/
/src/main/resources/
/src/test/java/
/src/test/resources/

난에 파일이 /src/test/resources/test.csv난에 단위 테스트에서 파일을로드 할/src/test/java/MyTest.java

작동하지 않는이 코드가 있습니다. "이러한 파일이나 디렉토리가 없습니다"라는 메시지가 표시됩니다.

BufferedReader br = new BufferedReader (new FileReader(test.csv))

나는 또한 이것을 시도했다

InputStream is = (InputStream) MyTest.class.getResourcesAsStream(test.csv))

이것은 또한 작동하지 않습니다. 를 반환합니다 null. Maven을 사용하여 프로젝트를 빌드하고 있습니다.


어떻게 작동하지 않습니까? 당신의 오류는 무엇입니까?
Daniel Kaplan

17
이것을 시도this.getClass().getResource("/test.csv")
SRy


@SRy 작동했습니다 (이것은 절대 경로 URL을 반환하므로) jar 파일을 항아리 내부로 작동하지 않고 절대 경로가 유효하지 않게되는 순간 상대 경로 자체로 재생할 수있는 방법이
있습니까

답변:


240

다음을 시도하십시오.

ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("test.csv");

위의 방법으로 문제가 해결되지 않으면 다양한 프로젝트가 다음 클래스에 추가되었습니다 : 1 (code here ). 2ClassLoaderUtil

해당 클래스를 사용하는 방법에 대한 몇 가지 예는 다음과 같습니다.

src \ main \ java \ com \ company \ test \ YourCallingClass.java
src \ main \ java \ com \ opensymphony \ xwork2 \ util \ ClassLoaderUtil.java
src \ main \ resources \ test.csv
// java.net.URL
URL url = ClassLoaderUtil.getResource("test.csv", YourCallingClass.class);
Path path = Paths.get(url.toURI());
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// java.io.InputStream
InputStream inputStream = ClassLoaderUtil.getResourceAsStream("test.csv", YourCallingClass.class);
InputStreamReader streamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(streamReader);
for (String line; (line = reader.readLine()) != null;) {
    // Process line
}

노트

  1. Wayback Machine 에서 참조하십시오 .
  2. 또한 GitHub에서 .

14
답을 위해 thx, 왜 우리가 왜이 특정 로더를 사용해야하지만 클래스의 로더는 사용하지 않아야하는지 설명해 주시겠습니까?
Hui Wang

1
큰, 내가 사용하던 너무 바보 Object.class.getClassLoader();이 제안 않습니다 - - 잘 거의가 주입 작업을하지 않았다 정적 컨텍스트에서, %20나에게주는 스페이스FileNotFoundException
ycomp

5
@ycomp getResource가 파일이 아닌 URL을 반환하기 때문에. java.net.URL의 getFile 메소드 는 URL을 파일로 변환 하지 않습니다 . URL의 경로와 쿼리 부분 만 반환합니다. 파일로 변환하려고 시도해서는 안됩니다. openStream을 호출하고 읽어보십시오.
VGR

이 프로젝트를 확인하고 리소스 폴더 스캔을 해결하십시오. github.com/fraballi/resources-folder-scanner
Felix Aballi

60

시험:

InputStream is = MyTest.class.getResourceAsStream("/test.csv");

IIRC getResourceAsStream()는 기본적으로 클래스 패키지와 관련이 있습니다.

@Terran이 지적했듯이 /파일 이름의 시작 부분에 를 추가하는 것을 잊지 마십시오


3
온전함을 추구하는 사람들을 위해이 게시물은 리소스를 String stackoverflow.com/a/35446009/544045
Trevor

12
"/"가 열쇠입니다.
Terran

33

다음은 Guava를 사용하는 빠른 솔루션입니다 .

import com.google.common.base.Charsets;
import com.google.common.io.Resources;

public String readResource(final String fileName, Charset charset) throws IOException {
        return Resources.toString(Resources.getResource(fileName), charset);
}

용법:

String fixture = this.readResource("filename.txt", Charsets.UTF_8)

28

Spring 프로젝트에서 흐름 코드를 사용해보십시오

ClassPathResource resource = new ClassPathResource("fileName");
InputStream inputStream = resource.getInputStream();

또는 비 봄 프로젝트

 ClassLoader classLoader = getClass().getClassLoader();
 File file = new File(classLoader.getResource("fileName").getFile());
 InputStream inputStream = new FileInputStream(file);

InputStream을 닫지 말아야합니까?
030

7

비 스프링 프로젝트 :

String filePath = Objects.requireNonNull(MyClass.class.getClassLoader().getResource("any.json")).getPath();

Stream<String> lines = Files.lines(Paths.get(filePath));

봄 프로젝트의 경우 한 줄 코드를 사용하여 resources 폴더 아래의 파일을 가져올 수도 있습니다.

File file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "any.json");

String content = new String(Files.readAllBytes(file.toPath()));

5

이제 maven created resources 디렉토리에서 글꼴을 읽는 소스 코드를 보여 드리겠습니다.

scr / main / resources / calibril.ttf

여기에 이미지 설명을 입력하십시오

Font getCalibriLightFont(int fontSize){
    Font font = null;
    try{
        URL fontURL = OneMethod.class.getResource("/calibril.ttf");
        InputStream fontStream = fontURL.openStream();
        font = new Font(Font.createFont(Font.TRUETYPE_FONT, fontStream).getFamily(), Font.PLAIN, fontSize);
        fontStream.close();
    }catch(IOException | FontFormatException ief){
        font = new Font("Arial", Font.PLAIN, fontSize);
        ief.printStackTrace();
    }   
    return font;
}

그것은 나를 위해 일했고 전체 소스 코드가 당신을 도울 수 있기를 바랍니다. 즐기십시오!


5

1.7 이후의 Java

 List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("test.csv").toURI()));

"/test.csv"를 사용해야합니다 (슬래시 참고).
레온

4
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("test.csv");

컨텍스트 ClassLoader를 사용하여 리소스를 찾으면 응용 프로그램 성능이 확실히 저하됩니다.


4
프로그래머는 항상 성능에 관심을 가져야합니다. 조기 최적화는 반드시 피해야하지만보다 효율적인 접근 방법을 아는 것이 항상 좋습니다. 그것은 LinkedList와 ArrayList의 차이점과 하나를 사용할 때를 아는 것과 같습니다.
Marvo

6
@Marvo : 프로그래머는 항상 품질, 기능 및 유지 보수 용이성에 대해 염려해야합니다. 성능은 대기열에 있습니다.
Igor Rodriguez

2

다음을 가져옵니다.

import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.util.ArrayList;

다음 메소드는 문자열의 ArrayList에 파일을 리턴합니다.

public ArrayList<String> loadFile(String filename){

  ArrayList<String> lines = new ArrayList<String>();

  try{

    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    InputStream inputStream = classloader.getResourceAsStream(filename);
    InputStreamReader streamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
    BufferedReader reader = new BufferedReader(streamReader);
    for (String line; (line = reader.readLine()) != null;) {
      lines.add(line);
    }

  }catch(FileNotFoundException fnfe){
    // process errors
  }catch(IOException ioe){
    // process errors
  }
  return lines;
}

2

나는 같은 문제에 직면했다 .

클래스 로더가 파일을 찾지 못했습니다. 즉, 아티팩트 (jar)에 압축되지 않았습니다. 프로젝트빌드 해야합니다 . 예를 들어 maven을 사용하면 다음과 같습니다.

mvn clean install

따라서 resources 폴더에 추가 한 파일은 maven 빌드로 들어가 응용 프로그램에서 사용할 수있게됩니다.

나는 내 대답을 유지하고 싶습니다 : 그것은 파일을 (다른 답변은 그 설명 할) 읽는 방법을 설명하지 않습니다, 그것은 응답 InputStreamresource있었다 널 (null) . 비슷한 답변이 여기 있습니다 .


1
고마워, 내가 내 마음을 잃고 있다고 생각에서 나를 구했다!
StuPointerException

1

getResource ()는 리소스 파일 src/main/resources에만 배치되어 제대로 작동했습니다 . src/main/resources말하는 src/test/java것 이외의 경로에있는 파일을 얻으 려면 정확하게 작성해야합니다.

다음 예제가 도움이 될 수 있습니다.

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

public class Main {
    public static void main(String[] args) throws URISyntaxException, IOException {
        URL location = Main.class.getProtectionDomain().getCodeSource().getLocation();
        BufferedReader br = new BufferedReader(new FileReader(location.getPath().toString().replace("/target/classes/", "/src/test/java/youfilename.txt")));
    }
}

0

IDE에서 실행할 때와 같이 Maven 빌드 jar을 실행하지 않을 때 코드가 작동합니까? 그렇다면 파일이 실제로 jar에 포함되어 있는지 확인하십시오. resources 폴더는에있는 pom 파일에 포함되어야합니다 <build><resources>.


Eclipse를 사용하고 IDE 자체에서 코드를 실행할 때. Java 코드의 "/ src / test / resources"에있는 리소스를 구체적으로 단위 테스트로로드하는 방법 표준 maven 프로젝트 구조를 고려하십시오.
Bhavesh

0

다음 클래스를 사용하여 resource에서 를로드 classpath하고 주어진에 문제가있는 경우 피팅 오류 메시지를 수신 할 수 있습니다 filePath.

import java.io.InputStream;
import java.nio.file.NoSuchFileException;

public class ResourceLoader
{
    private String filePath;

    public ResourceLoader(String filePath)
    {
        this.filePath = filePath;

        if(filePath.startsWith("/"))
        {
            throw new IllegalArgumentException("Relative paths may not have a leading slash!");
        }
    }

    public InputStream getResource() throws NoSuchFileException
    {
        ClassLoader classLoader = this.getClass().getClassLoader();

        InputStream inputStream = classLoader.getResourceAsStream(filePath);

        if(inputStream == null)
        {
            throw new NoSuchFileException("Resource file not found. Note that the current directory is the source folder!");
        }

        return inputStream;
    }
}

0

/scr/main/resources폴더를 추가 하여이 문제를 해결했습니다.Java Build Path

여기에 이미지 설명을 입력하십시오


이것을 시도하지만 이것은 해결책이 아닙니다
Jasonw

0

실행중인 jar와 IDE 모두에서 다음과 같이 작성하여 작동합니다.

 InputStream schemaStream = ProductUtil.class.getClassLoader().getResourceAsStream(jsonSchemaPath);
            byte[] buffer = new byte[schemaStream.available()];
            schemaStream.read(buffer);

        File tempFile = File.createTempFile("com/package/schema/testSchema", "json");
        tempFile.deleteOnExit();
        FileOutputStream out = new FileOutputStream(tempFile);
        out.write(buffer);

파일 구조는 어떻습니까?
luckydonald


0

com.google.common.io.Resources.getResource를 사용하여 파일의 URL을 읽은 다음 java.nio.file.Files를 사용하여 파일의 컨텐츠를 가져와 파일의 컨텐츠를 읽을 수 있습니다.

URL urlPath = Resources.getResource("src/main/resource");
List<String> multilineContent= Files.readAllLines(Paths.get(urlPath.toURI()));

-2

"class"또는 "ClassLoader"에 대한 참조없이 작동하도록합니다.

'example.file'파일의 위치와 앱이 실행되는 작업 디렉토리가 home / mydocuments / program / projects / myapp 인 세 가지 시나리오가 있다고 가정 해 보겠습니다.

a) 작업 디렉토리의 하위 폴더 인 myapp / res / files / example.file

b) 작업 디렉토리에 종속되지 않은 하위 폴더 : projects / files / example.file

b2) 작업 디렉토리에 종속되지 않은 다른 하위 폴더 : program / files / example.file

c) 루트 폴더 : home / mydocuments / files / example.file (Linux; Windows의 경우 home /을 C :로 대체)

1) 올바른 길 찾기 : a) String path = "res/files/example.file"; b) String path = "../projects/files/example.file"b2) String path = "../../program/files/example.file" c)String path = "/home/mydocuments/files/example.file"

기본적으로 루트 폴더 인 경우 슬래시로 경로 이름을 시작하십시오. 하위 폴더 인 경우 경로 이름 앞에 슬래시가 없어야합니다. 하위 폴더가 작업 디렉토리의 하위 폴더가 아닌 경우 "../"를 사용하여 해당 디렉토리로 cd해야합니다. 이것은 시스템이 한 폴더 위로 올라가도록 지시합니다.

2) 올바른 경로를 전달하여 File 객체를 만듭니다.

File file = new File(path);

3) 이제 가십시오 :

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