[英]Read file from resources folder in Spring Boot
我正在使用 Spring Boot 和json-schema-validator
。 我正在嘗試從resources
文件夾中讀取一個名為jsonschema.json
的文件。 我嘗試了幾種不同的方法,但無法正常工作。 這是我的代碼。
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)
我的代碼做錯了什么?
在花了很多時間試圖解決這個問題之后,終於找到了一個有效的解決方案。 該解決方案利用了 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;
}
}
回答一些對評論的關注:
很確定我使用java -jar target/image-service-slave-1.0-SNAPSHOT.jar
在 Amazon EC2 上運行了這個
查看我的 github 存儲庫: https : //github.com/johnsanthosh/image-service找出從 JAR 運行它的正確方法。
非常簡短的回答:您正在類加載器的類而不是目標類的范圍內尋找資源。 這應該有效:
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 年更新
最重要的是,如果您想將資源文件作為字符串讀取,例如在您的測試中,您可以使用這些靜態 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");
如果您在 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);
花了太多時間回到這個頁面,所以就把這個留在這里:
File file = new ClassPathResource("data/data.json").getFile();
讀取文件的最簡單方法是:
Resource resource = new ClassPathResource("jsonSchema.json");
FileInputStream file = new FileInputStream(resource.getFile());
在此處查看我的答案: https : //stackoverflow.com/a/56854431/4453282
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
使用這兩個進口。
宣布
@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部署后
要可靠地從 Spring 引導應用程序中的資源獲取文件:
InputStream
, URL
而不是File
resources
中讀取文件public class SpringBootResourcesApplication {
public static void main(String[] args) throws Exception {
ClassPathResource resource = new ClassPathResource("/hello", SpringBootResourcesApplication.class);
try (InputStream inputStream = resource.getInputStream()) {
String string = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8);
System.out.println(string);
}
}
}
ClassPathResource
是 Spring 的Resource
實現——加載資源的抽象方式。 它使用ClassPathResource(String, Class<?>)
構造函數進行實例化:
/hello
是文件的路徑
ClassLoader
而不是Class
,則可以省略斜杠Class
加載資源
Class
而不是ClassLoader
,因為ClassLoader.getResource
與Class.getResource
中的 Class.getResource 不同項目結構:
├── mvnw ├── mvnw.cmd ├── pom.xml └── src └── main ├── java │ └── com │ └── caco3 │ └── springbootresources │ └── SpringBootResourcesApplication.java └── resources ├── application.properties └── hello
上面的示例適用於 IDE 和 jar
File
InputStream
和URL
File
,因為並非總是可以從類路徑資源中獲取它
public class SpringBootResourcesApplication { public static void main(String[] args) throws Exception { ClassLoader classLoader = SpringBootResourcesApplication.class.getClassLoader(); File file = new File(classLoader.getResource("hello").getFile()); Files.readAllLines(file.toPath(), StandardCharsets.UTF_8).forEach(System.out::println); } }
但失敗: java.nio.file.NoSuchFileException: file:/home/caco3/IdeaProjects/spring-boot-resources/target/spring-boot-resources-0.0.1-SNAPSHOT.jar./BOOT-INF/classes./hello at java.base/sun.nio.fs.UnixException:translateToIOException(UnixException.java.92) at java.base/sun.nio.fs.UnixException:rethrowAsIOException(UnixException.java.111) at java.base/sun.nio.fs.UnixException:rethrowAsIOException(UnixException.java:116)
當 Spring 啟動 jar 運行時InputStream
或URL
JsonLoader.fromFile
可以替換為JsonLoader.fromURL
方法:它接受URL
Spring 框架支持通過ClassPathResource
訪問類路徑資源
你可以使用它:
resources
中讀取文件的例子@Value
: @SpringBootApplication public class SpringBootResourcesApplication implements ApplicationRunner { @Value("classpath:/hello") // Do not use field injection private Resource resource; public static void main(String[] args) throws Exception { SpringApplication.run(SpringBootResourcesApplication.class, args); } @Override public void run(ApplicationArguments args) throws Exception { try (InputStream inputStream = resource.getInputStream()) { String string = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); System.out.println(string); } } }
ResourceLoader
器: @SpringBootApplication public class SpringBootResourcesApplication implements ApplicationRunner { @Autowired // do not use field injection private ResourceLoader resourceLoader; public static void main(String[] args) throws Exception { SpringApplication.run(SpringBootResourcesApplication.class, args); } @Override public void run(ApplicationArguments args) throws Exception { Resource resource = resourceLoader.getResource("/hello"); try (InputStream inputStream = resource.getInputStream()) { String string = new String(inputStream.readAllBytes(), StandardCharsets.UTF_8); System.out.println(string); } } }
陷入同樣的問題,這對我有幫助
URL resource = getClass().getClassLoader().getResource("jsonschema.json");
JsonNode jsonNode = JsonLoader.fromURL(resource);
下面是我的工作代碼。
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));
希望對大家有所幫助!
將資源目錄中的類路徑中的資源解析為字符串的最簡單方法是以下一行。
作為字符串(使用 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"));
這是我的解決方案。 可能會幫助某人;
它返回 InputStream,但我假設您也可以從中讀取。
InputStream is = Thread.currentThread().getContextClassLoader().getResourceAsStream("jsonschema.json");
對我來說,這個錯誤有兩個修復。
我使用 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);
}
}
}
Spring 提供了ResourceLoader
可以用來加載文件。
@Autowired
ResourceLoader resourceLoader;
// path could be anything under resources directory
File loadDirectory(String path){
Resource resource = resourceLoader.getResource("classpath:"+path);
try {
return resource.getFile();
} catch (IOException e) {
log.warn("Issue with loading path {} as file", path);
}
return null;
}
參考這個鏈接。
如果你在你的項目中使用 maven 資源過濾器,你需要配置在 pom.xml 中加載什么樣的文件。 如果不這樣做,無論您選擇加載資源的哪個類,都不會找到它。
pom.xml
<resources>
<resource>
<directory>${project.basedir}/src/main/resources</directory>
<filtering>true</filtering>
<includes>
<include>**/*.properties</include>
<include>**/*.yml</include>
<include>**/*.yaml</include>
<include>**/*.json</include>
</includes>
</resource>
</resources>
下面在 IDE 中工作並在終端中將其作為 jar 運行,
import org.springframework.core.io.Resource;
@Value("classpath:jsonschema.json")
Resource schemaFile;
JsonSchemaFactory factory = JsonSchemaFactory.getInstance(SpecVersion.VersionFlag.V4);
JsonSchema jsonSchema = factory.getSchema(schemaFile.getInputStream());
只是將我的解決方案與所有其他答案一起添加為另外 2 美分。 我正在使用 Spring DefaultResourceLoader來獲取ResourceLoader 。 然后Spring FileCopyUtils將資源文件的內容轉為字符串。
import static java.nio.charset.StandardCharsets.UTF_8;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.io.UncheckedIOException;
import org.springframework.core.io.DefaultResourceLoader;
import org.springframework.core.io.Resource;
import org.springframework.core.io.ResourceLoader;
import org.springframework.util.FileCopyUtils;
public class ResourceReader {
public static String readResourceFile(String path) {
ResourceLoader resourceLoader = new DefaultResourceLoader();
Resource resource = resourceLoader.getResource(path);
return asString(resource);
}
private static String asString(Resource resource) {
try (Reader reader = new InputStreamReader(resource.getInputStream(), UTF_8)) {
return FileCopyUtils.copyToString(reader);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
}
這是一個使用ResourceUtils
和 Java 11 Files.readString
的解決方案,它負責 UTF-8 編碼和資源關閉
import org.json.JSONObject;
import org.springframework.util.ResourceUtils;
public JSONObject getJsonData() throws IOException {
//file path : src/main/resources/assets/data.json
File file = ResourceUtils.getFile("classpath:assets/data.json");
String data = Files.readString(file.toPath());
return new JSONObject(data);
}
但是在 OpenShift 上部署應用程序后,資源無法訪問。 所以正確的解決方案是
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.springframework.util.FileCopyUtils.copyToByteArray;
import org.springframework.core.io.ClassPathResource;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
public JsonNode getJsonData() throws IOException {
ClassPathResource classPathResource = new
ClassPathResource("assets/data.json");
byte[] byteArray =
copyToByteArray(classPathResource.getInputStream());
return new ObjectMapper() //
.readTree(new String(byteArray, UTF_8));
}
我認為問題出在放置項目的文件夾名稱中的空間內。 /home/user/Dev/Java/Java%20Programs/SystemRoutines/target/classes/jsonschema.json
Java 程序之間有空格。重命名文件夾名稱應該可以使它工作
如果您使用的是spring
和jackson
(大多數較大的應用程序會),那么使用一個簡單的 oneliner:
JsonNode json = new ObjectMapper().readTree(new ClassPathResource("filename").getFile());
我有同樣的問題,因為我只需要獲取文件路徑來發送到文件輸入流,我就這樣做了。
String pfxCertificate ="src/main/resources/cert/filename.pfx";
String pfxPassword = "1234";
FileInputStream fileInputStream = new FileInputStream(pfxCertificate));
使用 Spring ResourceUtils.getFile()你不必注意絕對路徑:)
private String readDictionaryAsJson(String filename) throws IOException {
String fileContent;
try {
File file = ResourceUtils.getFile("classpath:" + filename);
Path path = file.toPath();
Stream<String> lines = Files.lines(path);
fileContent = lines.collect(Collectors.joining("\n"));
} catch (IOException ex) {
throw ex;
}
return new fileContent;
}
嘗試這個:
在 application.properties
app.jsonSchema=classpath:jsonschema.json
在您的屬性 pojo 上:
注意:您可以使用任何首選方式從 application.properties 讀取配置。
@Configuration
@ConfigurationProperties(prefix = "app")
public class ConfigProperties {
private Resource jsonSchema;
// standard getters and setters
}
在您的 class 中,從 Properties Pojo 中讀取資源:
//Read the Resource and get the Input Stream
try (InputStream inStream = configProperties.getJsonSchema().getInputStream()) {
//From here you can manipulate the Input Stream as desired....
//Map the Input Stream to a Map
ObjectMapper mapper = new ObjectMapper();
Map <String, Object> jsonMap = mapper.readValue(inStream, Map.class);
//Convert the Map to a JSON obj
JSONObject json = new JSONObject(jsonMap);
} catch (Exception e) {
e.printStackTrace();
}
您需要清理路徑並將 %20 替換為空格,或重命名您的目錄。 然后它應該工作。
FileNotFoundException: /home/user/Dev/Java/Java%20Programs/SystemRoutines/target/classes/jsonschema.json
如今,在 2023 年,Java 位用戶應該能夠更輕松地讀取類路徑文件。 使用簡單的指令,例如new File("classpath:path-to-file")
。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.