Lesen Sie die Datei aus dem Ressourcenordner in Spring Boot

81

Ich benutze Spring Boot und json-schema-validator. Ich versuche, eine jsonschema.jsonaus dem resourcesOrdner aufgerufene Datei zu lesen . Ich habe ein paar verschiedene Möglichkeiten ausprobiert, aber ich kann es nicht zum Laufen bringen. Das ist mein Code.

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

Dies ist der Speicherort der Datei.

Geben Sie hier die Bildbeschreibung ein

Und hier kann ich die Datei im classesOrdner sehen.

Geben Sie hier die Bildbeschreibung ein

Aber wenn ich den Code ausführe, erhalte ich den folgenden Fehler.

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

Was mache ich falsch in meinem Code?

g3blv
quelle
Kannst du das versuchen? ClassLoader classLoader = getClass().getClassLoader(); JsonNode mySchema = JsonLoader.getJson(classLoader.getResourceAsStream("jsonschema.json"));
harschavmb

Antworten:

86

Nachdem ich viel Zeit damit verbracht hatte, dieses Problem zu lösen, fand ich endlich eine Lösung, die funktioniert. Die Lösung verwendet die ResourceUtils von Spring. Sollte auch für JSON-Dateien funktionieren.

Vielen Dank für die gut geschriebene Seite von Lokesh Gupta: Blog

Geben Sie hier die Bildbeschreibung ein

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

Um einige Bedenken zu den Kommentaren zu beantworten:

Ich bin mir ziemlich sicher, dass dies auf Amazon EC2 läuft java -jar target/image-service-slave-1.0-SNAPSHOT.jar

Schauen Sie sich mein Github-Repo an: https://github.com/johnsanthosh/image-service, um herauszufinden, wie dies von einem JAR aus richtig ausgeführt werden kann.

John
quelle
1
Danke John, dass du das hinzugefügt hast. Dies funktioniert und ist sicherlich ein besserer Ansatz bei der Verwendung von ResourceUtil.
Athar
1
@ Athar Ich bin froh, dass ich helfen konnte.
John
37
Dies funktioniert nur, wenn Sie versuchen, die Anwendung über die IDE auszuführen. Wenn Sie jedoch das JAR ausführen, wird die Datei nicht für Sie gefunden.
Hassan Mudassir
9
Stimmen Sie Hassan zu, wir sollten stattdessen verwenden, new ClassPathResource("filename").getInputStream()wenn Sie die Anwendung von jar ausführen. Detail
Jingchao Luan
2
Stimmen Sie Hassan zu. Als Einschränkung ist ResourceUtils Javadoc klar, dass die Klasse hauptsächlich für den internen Gebrauch bestimmt ist. Überprüfen Sie auch stackoverflow.com/questions/25869428/…
Eric Jiang
30

Sehr kurze Antwort: Sie suchen Ihre Immobilie im Rahmen eines bestimmten Klassenladeprogramms anstelle Ihrer Zielklasse. Das sollte funktionieren:

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

Siehe auch:

PS: Es kann ein Problem auftreten, wenn das Projekt auf einem Computer kompiliert und anschließend auf einem anderen Computer gestartet wurde oder Sie Ihre App in Docker ausführen. In diesem Fall können Pfade zu Ihrem Ressourcenordner ungültig sein. In diesem Fall ist es besser, zur Laufzeit die Pfade zu Ihren Ressourcen zu bestimmen:

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

Update von 2020

Wenn Sie beispielsweise die Ressourcendatei in Ihren Tests als Zeichenfolge lesen möchten, können Sie außerdem die folgenden statischen Utils-Methoden verwenden:

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

Anwendungsbeispiel:

String soapXML = getResourceFileAsString("some_folder_in_resources/SOPA_request.xml");
povis
quelle
2
getClass().getResource("jsonschema.json")kehrt zurück null. Ich habe auch versucht, ClassPathResource res = new ClassPathResource("jsonschema.json")was gerade zurückkommt jsonschema.json. Hat das etwas damit zu tun, dass ich Spring Boot verwende?
G3blv
@ g3blv In Bezug auf getClass().getResource("jsonschema.json")Rücksendungen nullkönnte ich auf dieses Thema auf stackoverflow.com/questions/26328040/… verweisen . Versuchen Sie außerdem, Ihr Projekt neu zu erstellen. Feedback wäre dankbar.
Povis
@ g3blv Ich habe ein Update zur Antwort bereitgestellt. Bitte überprüfen Sie
povis
1
@povisenko Ich würde vorschlagen, dass Sie eine Ausnahme auslösen, wenn sie isleer ist. Dies bedeutet, dass die gesuchte Datei / Ressource nicht vorhanden ist.
Endertunc
vollständige Antwort. Funktioniert sowohl in der IDE als auch für das Glas. Vielen Dank.
Digao
22

Wenn Sie zum Beispiel einen Konfigurationsordner unter Ressourcenordner haben, habe ich versucht, dass diese Klasse perfekt funktioniert. Ich hoffe, sie ist nützlich

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

//Read File Content
String content = new String(Files.readAllBytes(file.toPath()));
System.out.println(content);
Ismail
quelle
3
Ich habe Ihre Lösung ausprobiert, sie funktioniert in IDE, aber wenn Sie einen Spring Jar Input Stream erstellen, hilft dies.
Ameya
11

Ich habe viel zu viel Zeit damit verbracht, auf diese Seite zurückzukehren, also lass das hier:

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

Siehe meine Antwort hier: https://stackoverflow.com/a/56854431/4453282

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

Verwenden Sie diese 2 Importe.

Erklären

@Autowired
ResourceLoader resourceLoader;

Verwenden Sie dies in einigen Funktionen

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

In Ihrem Fall können Sie, wenn Sie die Datei benötigen, Folgendes verwenden

File file = resource.getFile()

Referenz: http://frugalisminds.com/spring/load-file-classpath-spring-boot/ Wie bereits in den vorherigen Antworten erwähnt, verwenden Sie keine ResourceUtils, es funktioniert nicht nach der Bereitstellung von JAR, dies funktioniert auch in IDE wie nach der Bereitstellung

sajal rajabhoj
quelle
5

Erstellen Sie einen JSON-Ordner in Ressourcen als Unterordner und fügen Sie dann eine JSON-Datei in einem Ordner hinzu. Anschließend können Sie den folgenden Code verwenden: Geben Sie hier die Bildbeschreibung ein

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

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

Dies funktioniert in Docker.

MostafaMashayekhi
quelle
3

In der gleichen Ausgabe stecken, hilft mir das

URL resource = getClass().getClassLoader().getResource("jsonschema.json");
JsonNode jsonNode = JsonLoader.fromURL(resource);
Govind Singh
quelle
Tatsächlich
povis
2

Hier ist meine Lösung. Kann jemandem helfen;

Es gibt InputStream zurück, aber ich gehe davon aus, dass Sie auch daraus lesen können.

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

Unten ist mein Arbeitscode.

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

Hoffe es hilft einem!

Bhaumik Thakkar
quelle
1

Für mich hatte der Fehler zwei Korrekturen.

  1. XML-Datei mit dem Namen SAMPLE.XML, die dazu führte, dass selbst die folgende Lösung fehlschlug, wenn sie auf aws ec2 bereitgestellt wurde. Das Update bestand darin, es in new_sample.xml umzubenennen und die unten angegebene Lösung anzuwenden.
  2. Lösungsansatz https://medium.com/@jonathan.henrique.smtp/reading-files-in-resource-path-from-jar-artifact-459ce00d2130

Ich habe Spring Boot als JAR verwendet und für die Java-Variante aws ec2 bereitgestellt. Die Lösung lautet wie folgt:

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.
quelle
0

Die einfachste Methode, um eine Ressource aus dem Klassenpfad im Ressourcenverzeichnis in einen String zu analysieren, ist der folgende Liner.

Als Zeichenfolge (unter Verwendung von Frühlingsbibliotheken):

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

Diese Methode verwendet das Dienstprogramm StreamUtils und überträgt die Datei als Eingabestream auf kompakte Weise in einen String.

Wenn Sie die Datei als Byte-Array verwenden möchten, können Sie grundlegende Java File I / O-Bibliotheken verwenden:

Als Byte-Array (Verwenden von Java-Bibliotheken):

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

Ich denke, das Problem liegt in dem Bereich im Ordnernamen, in dem Ihr Projekt platziert ist. /home/user/Dev/Java/Java%20Programs/SystemRoutines/target/classes/jsonschema.json

Zwischen den Java-Programmen ist Platz. Durch das Umbenennen des Ordnernamens sollte dies funktionieren

Sam
quelle