Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/file/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 从jar中读取资源文件_Java_File_Jar_Resources_Embedded Resource - Fatal编程技术网

Java 从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

我想从我的jar中读取一个资源,如下所示:

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=新BufferedReadernew InputStreamReaderin; 只要file.txt资源在类路径上可用,那么无论file.txt资源是在类/目录中还是在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.getResourceAsStreamfile.txt访问它

提取.jar文件后,将文件放在根目录下,它应该位于根目录下,然后使用Thread.currentThread.getContextClassLoader.getResourceAsStreamfile.txt访问它


当jar用作插件时,第一个选项可能不起作用。

请确保使用正确的分隔符。我将相对路径中的所有/替换为File.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内部和外部都有效的解决方案

使用PathMatchingResourcePatternResolver

注意:它也适用于弹簧靴

在本例中,我正在读取src/main/resources/my_文件夹中的一些文件:


您可以使用类加载器,它将从类路径中读取根路径,而不在开始时使用/

InputStream in = getClass().getClassLoader().getResourceAsStream("file.txt"); 
BufferedReader reader = new BufferedReader(new InputStreamReader(in));
由于某些原因,当我将web应用程序部署到WildFly 14时,classLoader.getResource始终返回null。从getClass.getClassLoader或Thread.currentThread.getContextClassLoader获取类加载器返回null

getClass.getClassLoader API文档说

返回类的类装入器。一些实现可能使用null来表示引导类加载器。如果该类是由引导类装入器装入的,则在此类实现中,该方法将返回null

如果您正在使用WildFly和您的web应用程序,请尝试以下方法


request.getServletContext.getResource返回了资源url。此处请求是ServletRequest的对象。

问题在于某些第三方库需要文件路径名而不是输入流。大多数答案都没有解决这个问题

在这种情况下,一种解决方法是将资源内容复制到临时文件中。下面的示例使用jUnit的临时文件夹


以下代码适用于Spring bootkotlin:

val authReader = InputStreamReader(javaClass.getResourceAsStream("/file1.json"))
我找到了解决办法

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作为依赖项启动。

谢谢,这非常有用,代码工作得很好,但我确实有一个问题,我需要确定InputStream是否像File.exists一样存在,以便我的游戏可以判断是否使用默认文件。谢谢。哦,顺便说一句,getClass.getResource**/folder**/file.txt之所以能让它工作,是因为我把那个文件夹和我的jar放在同一个目录下
:.getResourceAsStream如果资源不存在,则返回null,因此可以作为您的exists测试。当然。。。别忘了关闭inputStream和BufferedReadery您不能像读取普通的旧文件一样读取jar压缩文件中的条目。这很糟糕,因为有很多库函数希望文件路径作为输入。URL.getFile不会将URL转换为文件名。它返回主机后的URL部分,所有百分比编码保持不变,因此如果路径包含任何非ASCII字符或URL中不允许的任何ASCII字符(包括空格),则结果将不会是现有文件名,即使URL是一个文件:URL。程序构建到jar后,这在内部不起作用。除非先转换为字符串并将其保存在本地,否则从jar中不起作用。如果您想从jar中的目录中读取文件,并带有任何文件编号,请参阅我不确定最初的问题是否涉及到Spring。前面评论中的链接引用了来自不同问题的Spring特定答案。我相信getResourceAsStream仍然是解决这个问题的一个更简单、更可移植的解决方案。欢迎使用。这并不能回答这个问题。一旦你有足够的钱,你就可以在任何岗位上工作。同时检查此项。这将删除文件中的换行符!非常感谢你的回答。。。第二个选项的另一个好处是它也可以从主方法工作,因为getClass只能从实例工作,而不能从静态方法工作。谢谢你把它记录下来。我很好奇没有JUnit还有什么其他选项。因为resourceName应该始终使用/作为分隔符,而不像decomposePath中的文件操作使用系统特定的文件分隔符,与path.split/相比,该方法不仅不必要地复杂,甚至是不正确的。此外,还不清楚为什么在不使用其结果时调用.toArraynew字符串[0]。什么是文件夹,哪个库是列表,什么是替换_现有。。。?请提供您的文章的完整信息。奇怪的是,这也是我使用嵌套资源的解决方案。我想知道为什么在其他帖子的答案中用斜杠来解释,我想这是因为路径是如何解释的/file.txt表示切换到当前目录并打开file.txt,而file.txt表示从当前位置打开file.txt。它们都指向同一个位置。对我来说,两者都可以在windows系统中工作。啊哈,在docker+linux环境中它对我不起作用。。。感谢您的陈述这里的certPath是什么?我使用了它,它起到了作用。.写它只是为了将来供任何人使用-javax.xml.ws.Service Service=javax.xml.ws.Service.createIridiumClientService.class.getClassLoader.getResourceiridium.wsdl,新QNameWWW_IRIDIUM_COM,IWS;这里的诀窍是确保您的文件夹看起来是正确的。检查目标文件夹以确定您的文件不适用于我的位置…我在jar中的资源中有.wsdl…但它仍然无法解析wsdl
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));