[英]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.