Spring Boot의 리소스 폴더에서 파일 읽기


89

저는 Spring Boot와 json-schema-validator. 폴더 jsonschema.json에서 라는 파일을 읽으려고 resources합니다. 몇 가지 다른 방법을 시도했지만 작동하지 않습니다. 이것은 내 코드입니다.

ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("jsonschema.json").getFile());
JsonNode mySchema = JsonLoader.fromFile(file);

이것은 파일의 위치입니다.

여기에 이미지 설명 입력

여기에서 classes폴더 의 파일을 볼 수 있습니다 .

여기에 이미지 설명 입력

하지만 코드를 실행하면 다음과 같은 오류가 발생합니다.

jsonSchemaValidator error: java.io.FileNotFoundException: /home/user/Dev/Java/Java%20Programs/SystemRoutines/target/classes/jsonschema.json (No such file or directory)

내 코드에서 내가 뭘 잘못하고 있니?


이것을 시도해 볼 수 있습니까? ClassLoader classLoader = getClass().getClassLoader(); JsonNode mySchema = JsonLoader.getJson(classLoader.getResourceAsStream("jsonschema.json"));
harshavmb

답변:


92

이 문제를 해결하기 위해 많은 시간을 보낸 후 마침내 작동하는 해결책을 찾았습니다. 이 솔루션은 Spring의 ResourceUtils를 사용합니다. json 파일에서도 작동합니다.

Lokesh Gupta의 잘 작성된 페이지에 감사드립니다 : 블로그

여기에 이미지 설명 입력

package utils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.ResourceUtils;

import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Properties;
import java.io.File;


public class Utils {

    private static final Logger LOGGER = LoggerFactory.getLogger(Utils.class.getName());

    public static Properties fetchProperties(){
        Properties properties = new Properties();
        try {
            File file = ResourceUtils.getFile("classpath:application.properties");
            InputStream in = new FileInputStream(file);
            properties.load(in);
        } catch (IOException e) {
            LOGGER.error(e.getMessage());
        }
        return properties;
    }
}

의견에 대한 몇 가지 우려 사항에 답변하려면 다음을 수행하십시오.

Amazon EC2에서 이것을 사용하여 java -jar target/image-service-slave-1.0-SNAPSHOT.jar

내 github 저장소를 살펴보십시오 : https://github.com/johnsanthosh/image-service 는 JAR에서 이것을 실행하는 올바른 방법을 알아냅니다.


1
이것을 추가 해주신 John에게 감사드립니다. 이것은 ResourceUtil을 사용하는 더 나은 접근 방식입니다.
Athar

1
@Athar 제가 도울 수있어서 기쁩니다.
John

39
이것은 IDE에서 응용 프로그램을 실행하려고 할 때만 작동하지만 jar를 실행하면 파일을 찾을 수 없습니다.
Hassan Mudassir 2008 년

11
Hassan에 동의합니다 new ClassPathResource("filename").getInputStream(). jar에서 애플리케이션을 실행하는 경우 대신 사용해야 합니다. 세부 정보
Jingchao Luan 19.04.03

2
Hassan과 동의하십시오. 주의 사항으로 ResourceUtils Javadoc은 클래스가 주로 내부 용이라는 점을 분명히합니다. 뿐만 아니라 체크 stackoverflow.com/questions/25869428/...
에릭 장쩌민에게

36

매우 짧은 대답 : 대상 클래스 대신 특정 클래스 로더의 범위에서 속성을 찾고 있습니다. 이것은 작동합니다.

File file = new File(getClass().getResource("jsonschema.json").getFile());
JsonNode mySchema = JsonLoader.fromFile(file);

또한 다음을 참조하십시오.

추신 : 프로젝트가 한 컴퓨터에서 컴파일 된 후 다른 컴퓨터에서 실행되거나 Docker에서 앱을 실행하는 경우 문제가 발생할 수 있습니다. 이 경우 리소스 폴더 경로가 유효하지 않을 수 있습니다. 이 경우 런타임에 리소스 경로를 결정하는 것이 좋습니다.

ClassPathResource res = new ClassPathResource("jsonschema.json");    
File file = new File(res.getPath());
JsonNode mySchema = JsonLoader.fromFile(file);

2020 년 업데이트

또한 테스트에서 리소스 파일을 문자열로 읽으려면 다음과 같은 정적 utils 메서드를 사용할 수 있습니다.

public static String getResourceFileAsString(String fileName) {
    InputStream is = getResourceFileAsInputStream(fileName);
    if (is != null) {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        return (String)reader.lines().collect(Collectors.joining(System.lineSeparator()));
    } else {
        throw new RuntimeException("resource not found");
    }
}

public static InputStream getResourceFileAsInputStream(String fileName) {
    ClassLoader classLoader = {CurrentClass}.class.getClassLoader();
    return classLoader.getResourceAsStream(fileName);
}

사용 예 :

String soapXML = getResourceFileAsString("some_folder_in_resources/SOPA_request.xml");

2
getClass().getResource("jsonschema.json")를 반환합니다 null. 나는 또한 ClassPathResource res = new ClassPathResource("jsonschema.json")단지 반환하는 것을 시도했다 jsonschema.json. 이것이 내가 Spring Boot를 사용하는 것과 관련이 있습니까?
g3blv

@ g3blv에 대한 getClass().getResource("jsonschema.json")반환 null나는이 주제를 참조 할 수 stackoverflow.com/questions/26328040/... . 그 위에 프로젝트를 다시 빌드하십시오. 피드백을 주시면 감사하겠습니다.
Serhii Povisenko

@ g3blv 내가 답변에 대한 업데이트를 제공했습니다. 확인하십시오
Serhii Povisenko

1
@povisenko is비어 있으면 예외를 던질 것을 제안합니다 . 찾고있는 파일 / 리소스가 존재하지 않음을 의미합니다.
endertunc

완전한 대답. IDE와 jar 모두에서 작동합니다. 감사.
Digao

24

예를 들어 Resources 폴더 아래에 config 폴더가 있다면이 클래스가 완벽하게 작동하기를 바랍니다.

File file = ResourceUtils.getFile("classpath:config/sample.txt")

//Read File Content
String content = new String(Files.readAllBytes(file.toPath()));
System.out.println(content);

3
솔루션을 시도했지만 IDE에서 작동하지만 스프링 jar 입력 스트림을 만들면 도움이 될 것입니다.
Ameya

13

이 페이지로 돌아 오는 데 너무 많은 시간을 소비 했으므로 여기에 그대로 두십시오.

File file = new ClassPathResource("data/data.json").getFile();

7

여기 내 대답을 참조하십시오 : https://stackoverflow.com/a/56854431/4453282

import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;

이 두 가지 가져 오기를 사용하십시오.

알리다

@Autowired
ResourceLoader resourceLoader;

일부 기능에서 사용

Resource resource=resourceLoader.getResource("classpath:preferences.json");

귀하의 경우 파일이 필요하므로 다음을 사용할 수 있습니다.

File file = resource.getFile()

참조 : http://frugalisminds.com/spring/load-file-classpath-spring-boot/ 이전 답변에서 이미 언급했듯이 ResourceUtils를 사용하지 마십시오 JAR 배포 후 작동하지 않습니다. 이것은 IDE에서도 작동합니다 배포 후


JAR에서는 작동하지 않습니다
Abhishek

5

리소스에 json 폴더를 하위 폴더로 만든 다음 폴더에 json 파일을 추가하면 다음 코드를 사용할 수 있습니다. 여기에 이미지 설명 입력

import com.fasterxml.jackson.core.type.TypeReference;

InputStream is = TypeReference.class.getResourceAsStream("/json/fcmgoogletoken.json");

이것은 Docker에서 작동합니다.



2

여기 내 해결책이 있습니다. 누군가를 도울 수 있습니다.

그것은 InputStream을 반환하지만 당신도 읽을 수 있다고 가정합니다.

InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("jsonschema.json");

1

아래는 내 작업 코드입니다.

List<sampleObject> list = new ArrayList<>();
File file = new ClassPathResource("json/test.json").getFile();
ObjectMapper objectMapper = new ObjectMapper();
sampleObject = Arrays.asList(objectMapper.readValue(file, sampleObject[].class));

도움이되기를 바랍니다!


1

나를 위해 버그에는 두 가지 수정 사항이 있습니다.

  1. aws ec2에 배포 할 때 아래 솔루션도 실패하는 SAMPLE.XML로 이름이 지정된 XML 파일. 수정 사항은 이름을 new_sample.xml로 변경하고 아래 제공된 솔루션을 적용하는 것입니다.
  2. 솔루션 접근 방식 https://medium.com/@jonathan.henrique.smtp/reading-files-in-resource-path-from-jar-artifact-459ce00d2130

Spring boot를 jar로 사용하고 솔루션의 aws ec2 Java 변형에 배포했습니다.

package com.test;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.core.io.Resource;


public class XmlReader {

    private static Logger LOGGER = LoggerFactory.getLogger(XmlReader.class);

  public static void main(String[] args) {


      String fileLocation = "classpath:cbs_response.xml";
      String reponseXML = null;
      try (ClassPathXmlApplicationContext appContext = new ClassPathXmlApplicationContext()){

        Resource resource = appContext.getResource(fileLocation);
        if (resource.isReadable()) {
          BufferedReader reader =
              new BufferedReader(new InputStreamReader(resource.getInputStream()));
          Stream<String> lines = reader.lines();
          reponseXML = lines.collect(Collectors.joining("\n"));

        }      
      } catch (IOException e) {
        LOGGER.error(e.getMessage(), e);
      }
  }
}

0

문자열로 구문 분석 된 리소스 디렉터리의 클래스 경로에서 리소스를 가져 오는 가장 간단한 방법은 다음 한 줄입니다.

문자열로 (Spring Libraries 사용) :

         String resource = StreamUtils.copyToString(
                new ClassPathResource("resource.json").getInputStream(), defaultCharset());

이 메서드는 StreamUtils 유틸리티를 사용하고 간결한 방식으로 파일을 입력 스트림으로 String에 스트리밍합니다.

파일을 바이트 배열로 원하는 경우 기본 Java 파일 I / O 라이브러리를 사용할 수 있습니다.

바이트 배열로 (Java 라이브러리 사용) :

byte[] resource = Files.readAllBytes(Paths.get("/src/test/resources/resource.json"));

0

문제는 프로젝트가 위치한 폴더 이름의 공간에 있다고 생각합니다. /home/user/Dev/Java/Java%20Programs/SystemRoutines/target/classes/jsonschema.json

Java 프로그램 사이에 공백이 있습니다. 폴더 이름을 바꾸면 작동합니다.

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