SpringBootのresourcesフォルダーからファイルを読み取ります


89

SpringBootとを使用してい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 2017年

回答:


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

コメントに関するいくつかの懸念に答えるには:

これをAmazonEC2で実行していたことは確かです java -jar target/image-service-slave-1.0-SNAPSHOT.jar

私のgithubリポジトリ(https://github.com/johnsanthosh/image-service) を見て、JARからこれを実行する正しい方法を見つけてください


1
これを追加してくれたジョンに感謝します。これは機能し、ResourceUtilを使用したより良いアプローチです。
Athar 2018年

1
@Athar私が助けることができてうれしいです。
ジョン

39
これは、IDEからアプリケーションを実行しようとした場合にのみ機能しますが、jarを実行すると、ファイルが見つかりません。
Hassan Mudassir 2018

11
Hassanに同意しnew ClassPathResource("filename").getInputStream()ます。代わりに、jarからアプリケーションを実行する場合に使用する必要があります。詳細
JingchaoLuan19年

2
ハッサンに同意します。注意点として、ResourceUtils Javadocは、クラスが主に内部で使用されることを明確にしています。チェックだけでなくstackoverflow.com/questions/25869428/...
エリック・江

36

非常に短い答え:ターゲットクラスではなく、特定のクラスローダーのスコープでプロパティを探しています。これは機能するはずです:

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

また、これを参照してください:

PSプロジェクトが1つのマシンでコンパイルされ、その後別のマシンで起動された場合、または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。これは私がSpringBootを使用していることと関係がありますか?
g3blv 2017年

返品に関する@ g3blvこのトピックstackoverflow.com/questions/26328040/…を参照できgetClass().getResource("jsonschema.json")ます。その上で、プロジェクトを再構築してみてください。フィードバックをいただければ幸いです。null
SerhiiPovisenko19年

@ g3blv回答の最新情報を提供しました。確認してください
SerhiiPovisenko20年

1
@povisenkois空の場合は例外をスローすることをお勧めします。それはあなたが探しているファイル/リソースがそこにないことを意味します。
endertunc

完全な答え。IDEとjarの両方で機能します。ありがとう。
ディガオ

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で動作しますが、Springjar入力ストリームを作成すると役立ちます。
アメヤ


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

私にとって、バグには2つの修正がありました。

  1. SAMPLE.XMLという名前のXmlファイル。これにより、awsec2にデプロイしたときに以下のソリューションでも失敗していました。修正は、名前を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

解析されたresourcesディレクトリのクラスパスから文字列にリソースを取り込む最も簡単な方法は、次の1つのライナーです。

文字列として(Springライブラリを使用):

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

このメソッドは、StreamUtilsユーティリティを使用して、ファイルを入力ストリームとして簡潔でコンパクトな方法で文字列にストリーミングします。

ファイルをバイト配列として使用する場合は、基本的な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.