Đọc tệp từ thư mục tài nguyên trong Spring Boot


82

Tôi đang sử dụng Spring Boot và json-schema-validator. Tôi đang cố đọc một tệp được gọi jsonschema.jsontừ resourcesthư mục. Tôi đã thử một số cách khác nhau nhưng tôi không thể làm cho nó hoạt động. Đây là mã của tôi.

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

Đây là vị trí của tệp.

nhập mô tả hình ảnh ở đây

Và ở đây tôi có thể thấy tệp trong classesthư mục.

nhập mô tả hình ảnh ở đây

Nhưng khi tôi chạy mã, tôi gặp lỗi sau.

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

Tôi đang làm gì sai trong mã của mình?


Bạn có thể thử cái này không? ClassLoader classLoader = getClass().getClassLoader(); JsonNode mySchema = JsonLoader.getJson(classLoader.getResourceAsStream("jsonschema.json"));
harshavmb

Câu trả lời:


87

Sau khi dành nhiều thời gian cố gắng giải quyết vấn đề này, cuối cùng đã tìm thấy một giải pháp hoạt động. Giải pháp sử dụng ResourceUtils của Spring. Cũng nên làm việc cho các tệp json.

Cảm ơn vì trang viết tốt của Lokesh Gupta: Blog

nhập mô tả hình ảnh ở đây

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;
    }
}

Để giải đáp một số băn khoăn trên các bình luận:

Khá chắc chắn rằng tôi đã chạy cái này trên Amazon EC2 bằng cách sử dụng java -jar target/image-service-slave-1.0-SNAPSHOT.jar

Xem repo github của tôi: https://github.com/johnsanthosh/image-service để tìm ra cách phù hợp để chạy điều này từ JAR.


1
Cảm ơn John đã thêm điều này. Điều này hoạt động và chắc chắn là một cách tiếp cận tốt hơn bằng cách sử dụng ResourceUtil.
Athar

1
@Athar Rất vui vì tôi có thể giúp đỡ.
John

37
Điều này sẽ chỉ hoạt động nếu bạn cố gắng chạy ứng dụng từ IDE nhưng khi bạn chạy jar, nó sẽ không tìm thấy tệp cho bạn.
Hassan Mudassir

9
Đồng ý với Hassan, thay vào đó chúng ta nên sử dụng new ClassPathResource("filename").getInputStream()nếu chạy ứng dụng từ jar. Chi tiết
Jingchao Luan

2
Đồng ý với Hassan. Như một lưu ý, ResourceUtils Javadoc rõ ràng rằng lớp này chủ yếu để sử dụng nội bộ. Đồng thời kiểm tra stackoverflow.com/questions/25869428/…
Eric Jiang,

30

Câu trả lời rất ngắn gọn: bạn đang tìm kiếm thuộc tính của mình trong phạm vi của một bộ tải lớp cụ thể thay vì lớp đích của bạn. Điều này sẽ hoạt động:

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

Ngoài ra, hãy xem cái này:

Tái bút có thể xảy ra sự cố nếu dự án đã được biên dịch trên một máy và sau đó được khởi chạy trên máy khác hoặc bạn chạy ứng dụng của mình trong Docker. Trong trường hợp này, các đường dẫn đến thư mục tài nguyên của bạn có thể không hợp lệ. Trong trường hợp này, tốt hơn là xác định đường dẫn đến tài nguyên của bạn trong thời gian chạy:

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

Cập nhật từ năm 2020

Trên hết, nếu bạn muốn đọc tệp tài nguyên dưới dạng Chuỗi trong các thử nghiệm của mình, chẳng hạn, bạn có thể sử dụng các phương thức utils tĩnh sau:

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);
}

Ví dụ về cách sử dụng:

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

2
getClass().getResource("jsonschema.json")lợi nhuận null. Tôi cũng đã thử ClassPathResource res = new ClassPathResource("jsonschema.json")mà chỉ trả lại jsonschema.json. Điều này có liên quan đến việc tôi đang sử dụng Spring Boot không?
g3blv

@ g3blv về getClass().getResource("jsonschema.json")lợi nhuận. nullTôi có thể tham khảo chủ đề này stackoverflow.com/questions/26328040/… . Trên hết, hãy cố gắng xây dựng lại dự án của bạn. Phản hồi sẽ được đánh giá cao.
povis

@ g3blv Tôi đã cung cấp thông tin cập nhật về câu trả lời, vui lòng kiểm tra
povis

1
@povisenko Tôi khuyên bạn nên ném ngoại lệ nếu istrống. Có nghĩa là tệp / tài nguyên bạn đang tìm kiếm không có ở đó.
thúc

câu trả lời hoàn chỉnh. Hoạt động cả trong IDE và bình. Cảm ơn.
Digao

22

nếu bạn có thư mục cấu hình ví dụ trong thư mục Tài nguyên, tôi đã thử Lớp này hoạt động hoàn toàn hy vọng sẽ hữu ích

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

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

3
Tôi đã thử giải pháp của bạn, nó hoạt động trong IDE nhưng khi bạn tạo luồng đầu vào Spring jar sẽ giúp ích.
Ameya

11

Đã dành quá nhiều thời gian để quay lại trang này nên chỉ cần để ở đây:

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

6

Xem câu trả lời của tôi tại đây: https://stackoverflow.com/a/56854431/4453282

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

Sử dụng 2 nhập khẩu này.

Khai báo

@Autowired
ResourceLoader resourceLoader;

Sử dụng cái này trong một số chức năng

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

Trong trường hợp của bạn, khi bạn cần tệp, bạn có thể sử dụng sau

File file = resource.getFile()

Tham khảo: http://frugalisminds.com/spring/load-file-classpath-spring-boot/ Như đã đề cập trong các câu trả lời trước, không sử dụng ResourceUtils nó không hoạt động sau khi triển khai JAR, điều này cũng sẽ hoạt động trong IDE như sau khi triển khai


5

tạo thư mục json trong tài nguyên dưới dạng thư mục con sau đó thêm tệp json vào thư mục sau đó bạn có thể sử dụng mã này: nhập mô tả hình ảnh ở đây

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

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

điều này hoạt động trong Docker.


3

bị mắc kẹt trong cùng một vấn đề, điều này giúp tôi

URL resource = getClass().getClassLoader().getResource("jsonschema.json");
JsonNode jsonNode = JsonLoader.fromURL(resource);

trên thực tế, đây là gần như giống như câu trả lời cho biết thêm chi tiết xem tại đây stackoverflow.com/questions/14739550/...
povis

2

Đây là giải pháp của tôi. Có thể giúp đỡ ai đó;

Nó trả về InputStream, nhưng tôi cho rằng bạn cũng có thể đọc từ nó.

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

1

Dưới đây là mã làm việc của tôi.

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));

Hy vọng nó sẽ giúp một!


1

Đối với tôi, lỗi có hai cách sửa.

  1. Tệp Xml được đặt tên là SAMPLE.XML khiến ngay cả giải pháp bên dưới cũng không thành công khi triển khai aws ec2. Cách khắc phục là đổi tên nó thành new_sample.xml và áp dụng giải pháp đưa ra bên dưới.
  2. Cách tiếp cận giải pháp https://medium.com/@jonathan.henrique.smtp/reading-files-in-resource-path-from-jar-artifact-459ce00d2130

Tôi đã sử dụng Spring boot dưới dạng jar và được triển khai cho phiên bản Java aws ec2 của giải pháp như sau:

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

Phương pháp đơn giản nhất để đưa một tài nguyên từ classpath trong thư mục tài nguyên được phân tích cú pháp thành một Chuỗi là một lớp lót sau.

Dưới dạng một chuỗi (Sử dụng Thư viện Mùa xuân):

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

Phương pháp này sử dụng tiện ích StreamUtils và truyền tệp dưới dạng luồng đầu vào vào Chuỗi một cách ngắn gọn súc tích.

Nếu bạn muốn tệp dưới dạng một mảng byte, bạn có thể sử dụng các thư viện I / O Tệp Java cơ bản:

Dưới dạng một mảng byte (Sử dụng Thư viện Java):

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

0

tôi nghĩ rằng vấn đề nằm trong khoảng trống trong tên thư mục nơi dự án của bạn được đặt. /home/user/Dev/Java/Java%20Programs/SystemRoutines/target/classes/jsonschema.json

có khoảng trống giữa các Chương trình Java. Đổi tên thư mục sẽ làm cho nó hoạt động

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.