Leer el archivo de la carpeta de recursos en Spring Boot

81

Estoy usando Spring Boot y json-schema-validator. Estoy intentando leer un archivo llamado jsonschema.jsondesde la resourcescarpeta. He intentado algunas formas diferentes pero no puedo hacer que funcione. Este es mi codigo.

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

Esta es la ubicación del archivo.

ingrese la descripción de la imagen aquí

Y aquí puedo ver el archivo en la classescarpeta.

ingrese la descripción de la imagen aquí

Pero cuando ejecuto el código, aparece el siguiente error.

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

¿Qué es lo que estoy haciendo mal en mi código?

g3blv
fuente
¿Puedes probar esto? ClassLoader classLoader = getClass().getClassLoader(); JsonNode mySchema = JsonLoader.getJson(classLoader.getResourceAsStream("jsonschema.json"));
harshavmb

Respuestas:

86

Después de pasar mucho tiempo tratando de resolver este problema, finalmente encontré una solución que funciona. La solución hace uso de ResourceUtils de Spring. También debería funcionar para archivos json.

Gracias por la página bien escrita de Lokesh Gupta: Blog

ingrese la descripción de la imagen aquí

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

Para responder algunas inquietudes sobre los comentarios:

Estoy bastante seguro de que tenía esto ejecutándose en Amazon EC2 usando java -jar target/image-service-slave-1.0-SNAPSHOT.jar

Mire mi repositorio de github: https://github.com/johnsanthosh/image-service para descubrir la forma correcta de ejecutar esto desde un JAR.

Juan
fuente
1
Gracias John por agregar esto. Esto funciona y, sin duda, es un mejor enfoque utilizando ResourceUtil.
Athar
1
@Athar Me alegro de poder ayudar.
John
37
Esto solo funcionará si intenta ejecutar la aplicación desde IDE, pero cuando ejecuta el jar no encontrará el archivo por usted.
Hassan Mudassir
9
De acuerdo con Hassan, deberíamos usar new ClassPathResource("filename").getInputStream()si ejecutamos la aplicación desde jar. Detail
Jingchao Luan
2
De acuerdo con Hassan. Como advertencia, ResourceUtils Javadoc tiene claro que la clase es principalmente para uso interno. Consulte también stackoverflow.com/questions/25869428/…
Eric Jiang
30

Respuesta muy breve: está buscando su propiedad en el alcance de un cargador de clases en particular en lugar de su clase de destino. Esto debería funcionar:

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

Además, mira esto:

PD: puede haber un problema si el proyecto se compiló en una máquina y luego se lanzó en otra o si ejecuta su aplicación en Docker. En este caso, las rutas a su carpeta de recursos pueden no ser válidas. En este caso, sería mejor determinar las rutas a sus recursos en tiempo de ejecución:

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

Actualización de 2020

Además de eso, si desea leer el archivo de recursos como una cadena en sus pruebas, por ejemplo, puede usar estos métodos de utilidades estáticas:

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

Ejemplo de uso:

String soapXML = getResourceFileAsString("some_folder_in_resources/SOPA_request.xml");
povis
fuente
2
getClass().getResource("jsonschema.json")devuelve null. También probé ClassPathResource res = new ClassPathResource("jsonschema.json")que acaba de regresar jsonschema.json. ¿Tiene esto algo que ver con que estoy usando Spring Boot?
g3blv
@ g3blv con respecto a las getClass().getResource("jsonschema.json")devoluciones null, podría referirme a este tema stackoverflow.com/questions/26328040/… . Además de eso, intente reconstruir su proyecto. Se agradecería recibir comentarios.
povis
@ g3blv Proporcioné una actualización sobre la respuesta, verifique
povis
1
@povisenko Te sugiero que lances una excepción si está isvacía. Significa que el archivo / recurso que está buscando no está allí.
Endertunc
respuesta completa. Funciona tanto en el IDE como para el jar. Gracias.
Digao
22

si tiene, por ejemplo, la carpeta de configuración en la carpeta de Recursos, probé esta clase funcionando perfectamente, espero que sea útil

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

//Read File Content
String content = new String(Files.readAllBytes(file.toPath()));
System.out.println(content);
Ismail
fuente
3
Probé su solución, funciona en IDE, pero cuando haga Spring Jar, el flujo de entrada ayudará.
Ameya
11

Pasé demasiado tiempo volviendo a esta página, así que dejaré esto aquí:

File file = new ClassPathResource("data/data.json").getFile();
Emmanuel Osimosu
fuente
6

Vea mi respuesta aquí: https://stackoverflow.com/a/56854431/4453282

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

Utilice estas 2 importaciones.

Declarar

@Autowired
ResourceLoader resourceLoader;

Usa esto en alguna función

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

En su caso, como necesita el archivo, puede utilizar el siguiente

File file = resource.getFile()

Referencia: http://frugalisminds.com/spring/load-file-classpath-spring-boot/ Como ya se mencionó en las respuestas anteriores, no use ResourceUtils, no funciona después de la implementación de JAR, esto también funcionará en IDE como después del despliegue

sajal rajabhoj
fuente
5

cree la carpeta json en los recursos como subcarpeta, luego agregue el archivo json en la carpeta y luego puede usar este código: ingrese la descripción de la imagen aquí

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

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

esto funciona en Docker.

MostafaMashayekhi
fuente
3

atrapado en el mismo problema, esto me ayuda

URL resource = getClass().getClassLoader().getResource("jsonschema.json");
JsonNode jsonNode = JsonLoader.fromURL(resource);
Govind Singh
fuente
en realidad, esto es casi lo mismo que la respuesta dada para obtener más detalles, consulte aquí stackoverflow.com/questions/14739550/…
povis
2

Aquí está mi solución. Puede ayudar a alguien;

Devuelve InputStream, pero supongo que también puede leerlo.

InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("jsonschema.json");
Erçin Akçay
fuente
1

A continuación se muestra mi código de trabajo.

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

¡Espero que ayude a uno!

Bhaumik Thakkar
fuente
1

Para mí, el error tenía dos correcciones.

  1. Archivo XML que se denominó SAMPLE.XML, lo que provocaba que incluso la siguiente solución fallara cuando se implementaba en aws ec2. La solución fue cambiarle el nombre a new_sample.xml y aplicar la solución que se proporciona a continuación.
  2. Enfoque de solución https://medium.com/@jonathan.henrique.smtp/reading-files-in-resource-path-from-jar-artifact-459ce00d2130

Estaba usando Spring Boot como jar y lo implementé en aws ec2 La variante de Java de la solución es la siguiente:

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);
      }
  }
}
Vijayakumar S
fuente
0

El método más simple para traer un recurso de la ruta de clase en el directorio de recursos analizado en una cadena es el siguiente trazador de líneas.

Como cadena (usando bibliotecas Spring):

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

Este método utiliza la utilidad StreamUtils y transmite el archivo como un flujo de entrada en una cadena de una manera concisa y compacta.

Si desea el archivo como una matriz de bytes, puede usar las bibliotecas de E / S de archivos Java básicas:

Como una matriz de bytes (usando bibliotecas Java):

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

Creo que el problema radica en el espacio en el nombre de la carpeta donde se coloca su proyecto. /home/user/Dev/Java/Java%20Programs/SystemRoutines/target/classes/jsonschema.json

hay espacio entre los programas Java. Cambiar el nombre de la carpeta debería hacer que funcione

sam
fuente