【问题标题】:How do I load a file from resource folder?如何从资源文件夹加载文件?
【发布时间】:2013-03-22 20:48:07
【问题描述】:

我的项目结构如下:

/src/main/java/
/src/main/resources/
/src/test/java/
/src/test/resources/

我在/src/test/resources/test.csv 中有一个文件,我想从/src/test/java/MyTest.java 的单元测试中加载该文件

我有这段代码不起作用。它抱怨“没有这样的文件或目录”。

BufferedReader br = new BufferedReader (new FileReader(test.csv))

我也试过了

InputStream is = (InputStream) MyTest.class.getResourcesAsStream(test.csv))

这也行不通。它返回null。我正在使用 Maven 构建我的项目。

【问题讨论】:

  • 不工作怎么办?你的错误是什么?
  • 试试这个this.getClass().getResource("/test.csv")
  • @SRy 它起作用了(因为这将给出绝对路径 url 作为回报)但是当我制作 jar 文件时它不起作用,因为它在 jar 中并且绝对路径变得无效,有没有办法播放与相对路径本身
  • @SRy,从现在到 2013 年之间的某个时间,这似乎已得到修复。我今天能够在没有初始 / 的情况下加载根资源。不过,我是getClass().getClassLoader().getResourceAsStream(filename)...也许这就是区别?

标签: java file maven


【解决方案1】:

尝试下一个:

ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("test.csv");

如果以上不行,各种项目已经添加了如下类:ClassLoaderUtil1(代码here)。2

以下是如何使用该类的一些示例:

src\main\java\com\company\test\YourCallingClass.java
src\main\java\com\opensymphony\xwork2\util\ClassLoaderUtil.java
src\main\resources\test.csv
// java.net.URL
URL url = ClassLoaderUtil.getResource("test.csv", YourCallingClass.class);
Path path = Paths.get(url.toURI());
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// java.io.InputStream
InputStream inputStream = ClassLoaderUtil.getResourceAsStream("test.csv", YourCallingClass.class);
InputStreamReader streamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(streamReader);
for (String line; (line = reader.readLine()) != null;) {
    // Process line
}

注意事项

  1. See itThe Wayback Machine 中。
  2. 也在GitHub

【讨论】:

  • 谢谢你的答案,你能解释一下为什么我们应该使用这个非常具体的加载器而不是类的那个吗?
  • 太棒了,我太愚蠢了,我在静态上下文中使用了Object.class.getClassLoader();,但它不起作用 - 这个建议确实有效 - 几乎,它为给我的空间注入了 %20 FileNotFoundException
  • @ycomp 因为 getResource 返回的是 URL,而不是文件。 java.net.URL 的 getFile 方法将 URL 转换为文件;它只返回 URL 的路径和查询部分。您甚至不应该尝试将其转换为文件;只需调用 openStream 并从中读取。
  • 检查这个项目,解决资源文件夹扫描:github.com/fraballi/resources-folder-scanner
  • @prayagupa 建议的一种方法仅适用于 Java 9 或更高版本,请参阅stackoverflow.com/questions/54269211/…
【解决方案2】:

试试:

InputStream is = MyTest.class.getResourceAsStream("/test.csv");

IIRC getResourceAsStream() 默认是相对于类的包的。

正如@Terran 所说,不要忘记在文件名的开头添加/

【讨论】:

【解决方案3】:

在 Spring 项目中尝试以下代码

ClassPathResource resource = new ClassPathResource("fileName");
InputStream inputStream = resource.getInputStream();

或者在非春季项目上

 ClassLoader classLoader = getClass().getClassLoader();
 File file = new File(classLoader.getResource("fileName").getFile());
 InputStream inputStream = new FileInputStream(file);

【讨论】:

  • InputStream不应该关闭吗?
【解决方案4】:

这是使用Guava 的一种快速解决方案:

import com.google.common.base.Charsets;
import com.google.common.io.Resources;

public String readResource(final String fileName, Charset charset) throws IOException {
        return Resources.toString(Resources.getResource(fileName), charset);
}

用法:

String fixture = this.readResource("filename.txt", Charsets.UTF_8)

【讨论】:

  • 文档说这是关于 getResource 方法的:'getResource(java.lang.String)' is declared in unstable class 'com.google.common.io.Resources' marked with @Beta。人们真的应该使用不稳定类的方法吗?
【解决方案5】:

非春季项目:

String filePath = Objects.requireNonNull(getClass().getClassLoader().getResource("any.json")).getPath();

Stream<String> lines = Files.lines(Paths.get(filePath));

或者

String filePath = Objects.requireNonNull(getClass().getClassLoader().getResource("any.json")).getPath();

InputStream in = new FileInputStream(filePath);

对于spring项目,也可以使用一行代码获取resources文件夹下的任意文件:

File file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "any.json");

String content = new String(Files.readAllBytes(file.toPath()));

【讨论】:

    【解决方案6】:

    对于java 1.7以后

     List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("test.csv").toURI()));
    

    如果您在 Spring echosystem 中,您也可以使用 Spring utils

    final val file = ResourceUtils.getFile("classpath:json/abcd.json");
    

    要了解更多幕后情况,请查看以下博客

    https://todzhang.com/blogs/tech/en/save_resources_to_files

    【讨论】:

    • 我必须使用“/test.csv”(注意斜线)。
    【解决方案7】:

    我遇到了the same issue

    类加载器没有找到该文件,这意味着它没有被打包到工件(jar)中。您需要构建项目。例如,使用 Maven:

    mvn clean package
    

    因此,您添加到资源文件夹的文件将进入 maven 构建并可供应用程序使用。

    我想保留我的答案:它没有解释如何读取文件(其他答案确实解释了这一点),它回答了 为什么 InputStreamresourcenull 。类似answer is here

    【讨论】:

    • 谢谢,让我免于想我疯了!
    【解决方案8】:
    ClassLoader loader = Thread.currentThread().getContextClassLoader();
    InputStream is = loader.getResourceAsStream("test.csv");
    

    如果您使用上下文 ClassLoader 来查找资源,那么肯定会降低应用程序的性能。

    【讨论】:

    • 程序员应该始终关注性能。虽然肯定要避免过早的优化,但知道采取更有效的方法总是好的。这就像知道 LinkedList 和 ArrayList 之间的区别以及何时使用其中之一。
    • @Marvo:程序员必须始终关注质量、功能和易于维护,性能排在首位。
    【解决方案9】:

    现在我正在说明从 maven 创建的资源目录中读取字体的源代码,

    scr/main/resources/calibril.ttf

    Font getCalibriLightFont(int fontSize){
        Font font = null;
        try{
            URL fontURL = OneMethod.class.getResource("/calibril.ttf");
            InputStream fontStream = fontURL.openStream();
            font = new Font(Font.createFont(Font.TRUETYPE_FONT, fontStream).getFamily(), Font.PLAIN, fontSize);
            fontStream.close();
        }catch(IOException | FontFormatException ief){
            font = new Font("Arial", Font.PLAIN, fontSize);
            ief.printStackTrace();
        }   
        return font;
    }
    

    它对我有用,希望整个源代码也能帮助你,享受!

    【讨论】:

    • 你能告诉我们Font类的全名吗?
    【解决方案10】:

    导入以下内容:

    import java.io.IOException;
    import java.io.FileNotFoundException;
    import java.io.BufferedReader;
    import java.io.InputStreamReader;
    import java.io.InputStream;
    import java.util.ArrayList;
    

    以下方法返回一个字符串数组列表中的文件:

    public ArrayList<String> loadFile(String filename){
    
      ArrayList<String> lines = new ArrayList<String>();
    
      try{
    
        ClassLoader classloader = Thread.currentThread().getContextClassLoader();
        InputStream inputStream = classloader.getResourceAsStream(filename);
        InputStreamReader streamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
        BufferedReader reader = new BufferedReader(streamReader);
        for (String line; (line = reader.readLine()) != null;) {
          lines.add(line);
        }
    
      }catch(FileNotFoundException fnfe){
        // process errors
      }catch(IOException ioe){
        // process errors
      }
      return lines;
    }
    

    【讨论】:

      【解决方案11】:

      getResource() 仅适用于 src/main/resources 中的资源文件。要获取位于src/main/resources 以外的路径的文件,比如src/test/java,您需要显式创建它。

      下面的例子可能对你有帮助

      import java.io.BufferedReader;
      import java.io.FileReader;
      import java.io.IOException;
      import java.net.URISyntaxException;
      import java.net.URL;
      
      public class Main {
          public static void main(String[] args) throws URISyntaxException, IOException {
              URL location = Main.class.getProtectionDomain().getCodeSource().getLocation();
              BufferedReader br = new BufferedReader(new FileReader(location.getPath().toString().replace("/target/classes/", "/src/test/java/youfilename.txt")));
          }
      }
      

      【讨论】:

        【解决方案12】:

        您可以使用 com.google.common.io.Resources.getResource 读取文件的 url,然后使用 java.nio.file.Files 读取文件的内容来获取文件内容。

        URL urlPath = Resources.getResource("src/main/resource");
        List<String> multilineContent= Files.readAllLines(Paths.get(urlPath.toURI()));
        

        【讨论】:

          【解决方案13】:

          如果您正在以静态方法加载文件,那么 ClassLoader classLoader = getClass().getClassLoader(); 这可能会给你一个错误。

          你可以试试这个 例如您要从资源加载的文件是资源 >>​​ 图片 >> Test.gif

          import org.springframework.core.io.ClassPathResource;
          import org.springframework.core.io.Resource;
          
          Resource resource = new ClassPathResource("Images/Test.gif");
          
              File file = resource.getFile();
          

          【讨论】:

            【解决方案14】:

            要从 src/resources 文件夹中读取文件,然后试试这个:

            DataSource fds = new FileDataSource(getFileHandle("images/sample.jpeg"));
            
            public static File getFileHandle(String fileName){
                   return new File(YourClassName.class.getClassLoader().getResource(fileName).getFile());
            }
            

            在非静态引用的情况下:

            return new File(getClass().getClassLoader().getResource(fileName).getFile());
            

            【讨论】:

              【解决方案15】:

              代码在不运行 Maven-build jar 时(例如从 IDE 运行时)是否有效?如果是这样,请确保该文件实际上包含在 jar 中。资源文件夹应该包含在 pom 文件中,在&lt;build&gt;&lt;resources&gt;

              【讨论】:

              • 使用 Eclipse 并从 IDE 本身运行代码时。我们如何在 Java 代码中加载位于“/src/test/resources”的资源,特别是在单元测试中。考虑一个标准的 Maven 项目结构。
              【解决方案16】:

              以下类可用于从classpath 加载resource,并在给定的filePath 出现问题时收到合适的错误消息。

              import java.io.InputStream;
              import java.nio.file.NoSuchFileException;
              
              public class ResourceLoader
              {
                  private String filePath;
              
                  public ResourceLoader(String filePath)
                  {
                      this.filePath = filePath;
              
                      if(filePath.startsWith("/"))
                      {
                          throw new IllegalArgumentException("Relative paths may not have a leading slash!");
                      }
                  }
              
                  public InputStream getResource() throws NoSuchFileException
                  {
                      ClassLoader classLoader = this.getClass().getClassLoader();
              
                      InputStream inputStream = classLoader.getResourceAsStream(filePath);
              
                      if(inputStream == null)
                      {
                          throw new NoSuchFileException("Resource file not found. Note that the current directory is the source folder!");
                      }
              
                      return inputStream;
                  }
              }
              

              【讨论】:

                【解决方案17】:
                this.getClass().getClassLoader().getResource("filename").getPath()
                

                【讨论】:

                  【解决方案18】:

                  即使我按照答案,也找不到我在测试文件夹中的文件。 重建项目解决了这个问题。似乎 IntelliJ 没有自动识别新文件。很讨厌发现。

                  【讨论】:

                    【解决方案19】:

                    我通过编写为在运行 jar 和 IDE 中都可以使用

                    InputStream schemaStream = 
                          ProductUtil.class.getClassLoader().getResourceAsStream(jsonSchemaPath);
                    byte[] buffer = new byte[schemaStream.available()];
                    schemaStream.read(buffer);
                    
                    File tempFile = File.createTempFile("com/package/schema/testSchema", "json");
                    tempFile.deleteOnExit();
                    FileOutputStream out = new FileOutputStream(tempFile);
                    out.write(buffer);
                    

                    【讨论】:

                    • 你的文件结构是什么样的?
                    【解决方案20】:

                    我让它在没有任何参考“类”或“类加载器”的情况下工作。

                    假设我们有三个场景,文件“example.file”的位置和您的工作目录(您的应用执行的位置)是 home/mydocuments/program/projects/myapp:

                    a)工作目录的子文件夹: myapp/res/files/example.file

                    b) 不属于工作目录的子文件夹: 项目/文件/example.file

                    b2)另一个不属于工作目录的子文件夹: 程序/文件/example.file

                    c)一个根文件夹: home/mydocuments/files/example.file(Linux;在 Windows 中将 home/ 替换为 C:)

                    1) 获取正确的路径: a)String path = "res/files/example.file"; b)String path = "../projects/files/example.file" b2)String path = "../../program/files/example.file" c)String path = "/home/mydocuments/files/example.file"

                    基本上,如果是根文件夹,则路径名以斜杠开头。 如果是子文件夹,路径名前不能有斜杠。如果子文件夹不是工作目录的后代,则必须使用“../” cd 到它。这告诉系统上一个文件夹。

                    2)通过传递正确的路径创建一个File对象:

                    File file = new File(path);
                    

                    3) 你现在可以开始了:

                    BufferedReader br = new BufferedReader(new FileReader(file));
                    

                    【讨论】:

                      猜你喜欢
                      • 2015-10-29
                      • 2011-01-31
                      • 2014-12-27
                      • 1970-01-01
                      • 2013-03-12
                      • 1970-01-01
                      • 1970-01-01
                      • 2018-06-03
                      相关资源
                      最近更新 更多