Java 从jar中读取资源文件
我想从我的jar中读取一个资源,如下所示:Java 从jar中读取资源文件,java,file,jar,resources,embedded-resource,Java,File,Jar,Resources,Embedded Resource,我想从我的jar中读取一个资源,如下所示: File file; file = new File(getClass().getResource("/file.txt").toURI()); BufferedReader reader = new BufferedReader(new FileReader(file)); //Read the file 在Eclipse中运行它时效果很好,但是如果我将它导出到一个jar中,然后运行它,就会出现一个IllegalArgumen
File file;
file = new File(getClass().getResource("/file.txt").toURI());
BufferedReader reader = new BufferedReader(new FileReader(file));
//Read the file
在Eclipse中运行它时效果很好,但是如果我将它导出到一个jar中,然后运行它,就会出现一个IllegalArgumentException:
Exception in thread "Thread-2"
java.lang.IllegalArgumentException: URI is not hierarchical
我真的不知道为什么,但通过一些测试,我发现如果我改变了
file = new File(getClass().getResource("/file.txt").toURI());
到
然后它的工作原理正好相反(它在jar中工作,但在eclipse中不工作)
我正在使用Eclipse,并且我的文件所在的文件夹位于类文件夹中。而不是试图将资源作为一个地址来寻址,只需请求返回一个,而不是通过:
InputStream in=getClass().getResourceAsStream(“/file.txt”);
BufferedReader reader=新的BufferedReader(新的InputStreamReader(in));
只要file.txt
资源在类路径上可用,那么无论file.txt
资源是在classes/
目录中还是在jar
中,这种方法都将以相同的方式工作
URI不是分层的
,因为jar文件中资源的URI看起来像这样:file:/example.jar/file.txt
。您不能像读取普通的旧文件一样读取jar
(一个zip
文件)中的条目
以下问题的答案很好地解释了这一点:
ClassLoader classLoader = getClass().getClassLoader();
File file = new File(classLoader.getResource("file/test.xml").getFile());
要访问jar中的文件,您有两个选项:
- 将文件放在与包名匹配的目录结构中(提取.jar文件后,它应该与.class文件位于同一目录中),然后使用
getClass().getResourceAsStream(“file.txt”)
- 将文件放在根目录下(提取.jar文件后,它应该在根目录下),然后使用
Thread.currentThread().getContextClassLoader().getResourceAsStream(“file.txt”)
当jar用作插件时,第一个选项可能不起作用。请确保使用正确的分隔符。我将相对路径中的所有
/
替换为文件.separator
。这在IDE中运行良好,但在构建JAR中不起作用。如果您使用的是spring,则可以使用以下方法从src/main/resources读取文件:
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import org.springframework.core.io.ClassPathResource;
public String readFileToString(String path) throws IOException {
StringBuilder resultBuilder = new StringBuilder("");
ClassPathResource resource = new ClassPathResource(path);
try (
InputStream inputStream = resource.getInputStream();
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream))) {
String line;
while ((line = bufferedReader.readLine()) != null) {
resultBuilder.append(line);
}
}
return resultBuilder.toString();
}
我以前遇到过这个问题,所以我为加载设置了备用方式。基本上,第一种方法在.jar文件中工作,第二种方法在eclipse或其他IDE中工作
public class MyClass {
public static InputStream accessFile() {
String resource = "my-file-located-in-resources.txt";
// this is the path within the jar file
InputStream input = MyClass.class.getResourceAsStream("/resources/" + resource);
if (input == null) {
// this is how we load file within editor (eg eclipse)
input = MyClass.class.getClassLoader().getResourceAsStream(resource);
}
return input;
}
}
到目前为止(2017年12月),这是我发现的唯一一个在IDE内外都有效的解决方案
使用路径匹配源模式解析器
注意:它也适用于spring boot
在本例中,我正在读取位于src/main/resources/my_文件夹中的一些文件:
try {
// Get all the files under this inner resource folder: my_folder
String scannedPackage = "my_folder/*";
PathMatchingResourcePatternResolver scanner = new PathMatchingResourcePatternResolver();
Resource[] resources = scanner.getResources(scannedPackage);
if (resources == null || resources.length == 0)
log.warn("Warning: could not find any resources in this scanned package: " + scannedPackage);
else {
for (Resource resource : resources) {
log.info(resource.getFilename());
// Read the file content (I used BufferedReader, but there are other solutions for that):
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resource.getInputStream()));
String line = null;
while ((line = bufferedReader.readLine()) != null) {
// ...
// ...
}
bufferedReader.close();
}
}
} catch (Exception e) {
throw new Exception("Failed to read the resources folder: " + e.getMessage(), e);
}
您可以使用类加载器,它将从类路径中读取根路径(开头不带“/”)
由于某种原因,
classLoader.getResource()
在我将web应用程序部署到WildFly 14时总是返回null。从getClass()
getClass().getClassLoader()
API文档说
“返回类的类加载器。某些实现可能使用null表示引导类加载器。如果引导类加载器加载了此类,则此方法在此类实现中将返回null。”
如果您正在使用WildFly和您的web应用程序,请尝试以下方法
request.getServletContext().getResource()
返回了资源url。此处请求是ServletRequest的对象。问题在于某些第三方库需要文件路径名而不是输入流。大多数答案都没有解决这个问题
在这种情况下,一种解决方法是将资源内容复制到临时文件中。下面的示例使用jUnit的临时文件夹
private List<String> decomposePath(String path){
List<String> reversed = Lists.newArrayList();
File currFile = new File(path);
while(currFile != null){
reversed.add(currFile.getName());
currFile = currFile.getParentFile();
}
return Lists.reverse(reversed);
}
private String writeResourceToFile(String resourceName) throws IOException {
ClassLoader loader = getClass().getClassLoader();
InputStream configStream = loader.getResourceAsStream(resourceName);
List<String> pathComponents = decomposePath(resourceName);
folder.newFolder(pathComponents.subList(0, pathComponents.size() - 1).toArray(new String[0]));
File tmpFile = folder.newFile(resourceName);
Files.copy(configStream, tmpFile.toPath(), REPLACE_EXISTING);
return tmpFile.getAbsolutePath();
}
私有列表分解路径(字符串路径){
List reversed=Lists.newArrayList();
文件currFile=新文件(路径);
while(currFile!=null){
add(currFile.getName());
currFile=currFile.getParentFile();
}
退货清单。反向(反向);
}
私有字符串writeResourceToFile(字符串resourceName)引发IOException{
ClassLoader=getClass().getClassLoader();
InputStream configStream=loader.getResourceAsStream(resourceName);
列表路径组件=分解路径(resourceName);
folder.newFolder(pathComponents.subList(0,pathComponents.size()-1).toArray(新字符串[0]);
File tmpFile=folder.newFile(resourceName);
复制(configStream,tmpFile.toPath(),替换现有文件);
返回tmpFile.getAbsolutePath();
}
以下代码适用于弹簧靴(kotlin):
我找到了解决办法
BufferedReader br = new BufferedReader(new InputStreamReader(Main.class.getResourceAsStream(path)));
将“Main”替换为编码它的java类。将“path”替换为jar文件中的路径
例如,如果将State1.txt放在包com.issac.state中,那么如果运行Linux或Mac,请键入路径“/com/issac/state/State1”。如果运行Windows,请键入路径“\com\issac\state\State1”。除非发生“未找到文件”异常,否则不要向文件添加.txt扩展名 这段代码在Eclipse和导出的Runnable JAR中都有效
private String writeResourceToFile(String resourceName) throws IOException {
File outFile = new File(certPath + File.separator + resourceName);
if (outFile.isFile())
return outFile.getAbsolutePath();
InputStream resourceStream = null;
// Java: In caso di JAR dentro il JAR applicativo
URLClassLoader urlClassLoader = (URLClassLoader)Cypher.class.getClassLoader();
URL url = urlClassLoader.findResource(resourceName);
if (url != null) {
URLConnection conn = url.openConnection();
if (conn != null) {
resourceStream = conn.getInputStream();
}
}
if (resourceStream != null) {
Files.copy(resourceStream, outFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
return outFile.getAbsolutePath();
} else {
System.out.println("Embedded Resource " + resourceName + " not found.");
}
return "";
}
就我而言,我终于成功了
import java.lang.Thread;
import java.io.BufferedReader;
import java.io.InputStreamReader;
final BufferedReader in = new BufferedReader(new InputStreamReader(
Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt"))
); // no initial slash in file.txt
我在这里尝试了所有提到的事情,所以让我重新表述我的问题
javax.xml.ws.Service service =
javax.xml.ws.Service
.create(new File("src/main/resources/wsdl/iridium/iridium.wsdl").toURI().toURL(),
new QName(WWW_IRIDIUM_COM, IWS));
这个wsdl文件在java项目中,我将使用一个jar,所以当我将这个jar导入到另一个项目中时,我得到了一个“未找到文件”异常,因为该项目正试图查看其资源文件夹以启动spring boot应用程序
我需要做哪些更改才能使这个项目从这个jar作为依赖项开始。谢谢,这非常有帮助,c
private String writeResourceToFile(String resourceName) throws IOException {
File outFile = new File(certPath + File.separator + resourceName);
if (outFile.isFile())
return outFile.getAbsolutePath();
InputStream resourceStream = null;
// Java: In caso di JAR dentro il JAR applicativo
URLClassLoader urlClassLoader = (URLClassLoader)Cypher.class.getClassLoader();
URL url = urlClassLoader.findResource(resourceName);
if (url != null) {
URLConnection conn = url.openConnection();
if (conn != null) {
resourceStream = conn.getInputStream();
}
}
if (resourceStream != null) {
Files.copy(resourceStream, outFile.toPath(), StandardCopyOption.REPLACE_EXISTING);
return outFile.getAbsolutePath();
} else {
System.out.println("Embedded Resource " + resourceName + " not found.");
}
return "";
}
import java.lang.Thread;
import java.io.BufferedReader;
import java.io.InputStreamReader;
final BufferedReader in = new BufferedReader(new InputStreamReader(
Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt"))
); // no initial slash in file.txt
javax.xml.ws.Service service =
javax.xml.ws.Service
.create(new File("src/main/resources/wsdl/iridium/iridium.wsdl").toURI().toURL(),
new QName(WWW_IRIDIUM_COM, IWS));