Читання файлу з папки ресурсів у 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's ResourceUtils. Повинна працювати і для файлів json.

Дякуємо за добре написану сторінку Локеша Гупти: Блог

введіть тут опис зображення

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
Дякуємо Джону за додавання цього. Це працює, і, звичайно, кращий підхід за допомогою ResourceUtil.
Атар

1
@Athar Радий, що я міг допомогти.
Джон

39
Це буде працювати, лише якщо ви спробуєте запустити програму з IDE, але під час запуску jar він не знайде для вас файл.
Hassan Mudassir

11
Погодьтеся з Хасаном, натомість нам слід використовувати, new ClassPathResource("filename").getInputStream()якщо запустити додаток з jar. Деталь
Jingchao Luan

2
Погодьтеся з Хасаном. Як застереження, ResourceUtils Javadoc ясно, що клас в основному призначений для внутрішнього використання. Перевірте також stackoverflow.com/questions/25869428/…
Ерік Цзян,

36

Дуже коротка відповідь: ви шукаєте своє майно в межах певного завантажувача класів, а не цільового класу. Це має спрацювати:

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

Також дивіться це:

PS може виникнути проблема, якщо проект був складений на одній машині, а після цього запущений на іншій або ви запустили програму в Docker. У цьому випадку шляхи до вашої папки ресурсів можуть бути недійсними. У цьому випадку було б краще визначити шляхи до ваших ресурсів під час виконання:

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

Оновлення з 2020 року

Крім того, якщо ви хочете прочитати файл ресурсу як рядок у своїх тестах, наприклад, ви можете використовувати такі статичні методи використання:

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/… . На додачу до цього спробуйте відновити свій проект. Будемо вдячні за відгуки.
Сергій Повісенко

@ g3blv Я надав оновлення щодо відповіді, будь ласка, перевірте
Сергій Повісенко

1
@povisenko Я б запропонував вам кинути виняток, якщо він isпустий. Це означає, що шуканого файлу / ресурсу немає.
endertunc

повна відповідь. Працює як в IDE, так і для jar. Дякую.
Digao

24

якщо у вас є, наприклад, конфігураційна папка в папці Resources, я спробував цей клас, що працює, сподіваюся, буде корисним

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, але коли ви створите весняний потік вводу, це допоможе.
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;

Використовуйте ці 2 імпорти.

Заявити

@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
Абхішек

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. Xml-файл, який отримав назву SAMPLE.XML, що спричинило помилку навіть наведеного нижче рішення при розгортанні в aws ec2. Виправлення полягало в тому, щоб перейменувати його на 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

Найпростіший спосіб перенести ресурс із шляху до класу в каталог ресурсів, проаналізований у рядок, - це наступний вкладиш.

Як рядок (з використанням весняних бібліотек):

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

Цей метод використовує StreamUtils утиліту і стисло і компактно передає файл як вхідний потік у рядок.

Якщо ви хочете, щоб файл був байтовим масивом, ви можете використовувати основні бібліотеки вводу-виводу Java-файлів:

Як байтовий масив (з використанням бібліотек 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 є простір. Перейменування назви папки повинно змусити її працювати

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.