如何从资源文件夹加载文件?


240

我的项目具有以下结构:

/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构建我的项目。


不行怎么办?你怎么了
Daniel Kaplan

17
试试这个this.getClass().getResource("/test.csv")
SRy 2013年


@SRy它起作用了(因为这将返回绝对路径url),但是当我制作jar文件时,由于它在jar中,并且绝对路径变得无效,所以它
不起作用

Answers:


240

尝试下一个:

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

如果上述方法不起作用,则已在以下类中添加了各种项目:1(代码在此处)。2ClassLoaderUtil

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

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. Wayback Machine中查看
  2. 同样在GitHub中

14
thx的答案,你能解释一下为什么我们应该使用这个非常特定的加载器而不是类的加载器吗?
王晖

1
太好了,我是如此愚蠢,以至于我在Object.class.getClassLoader();一个无效的静态上下文中使用-这个建议确实有效-几乎可以,它注入%20了空间,给了我FileNotFoundException
ycomp

5
@ycomp因为getResource返回URL,而不是文件。java.net.URL的getFile方法不会将URL转换为文件。它只返回URL的路径和查询部分。您甚至都不应该尝试将其转换为文件。只需调用openStream并从中读取。
VGR

检查该项目,解决资源文件夹扫描问题:github.com/fraballi/resources-folder-scanner
Felix Aballi

60

尝试:

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

getResourceAsStream()默认情况下,IIRC 是相对于类的包的。

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


3
对于那些寻求理智的人,这篇文章为您提供了获取资源的全部途径String stackoverflow.com/a/35446009/544045
Trevor,

12
“ /”是关键。
Terran

33

这是使用番石榴的一种快速解决方案:

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)

28

在Spring项目上尝试Flowing代码

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吗?
030

7

非春季项目:

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

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

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

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

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

5

现在,我将说明从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;
}

它为我工作,并希望整个源代码也能对您有所帮助!


5

对于1.7之后的 Java

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

我必须使用“ /test.csv”(注意斜线)。
里昂,

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

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


4
程序员应始终关注性能。虽然一定要避免过早的优化,但是知道采取更有效的方法总是好的。这就像知道LinkedList和ArrayList之间的区别以及何时使用一个或另一个有关。
Marvo

6
@Marvo:程序员必须始终关注质量,功能和易于维护,性能迫在眉睫。
伊戈尔·罗德里格斯

2

导入以下内容:

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

以下方法在字符串的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;
}

2

我面临着同样的问题

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

mvn clean install

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

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


1
谢谢,使我免于以为我迷失了方向!
StuPointerException

1

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")));
    }
}

0

当不运行Maven-build jar时,例如从IDE中运行时,代码是否起作用?如果是这样,请确保文件实际上包含在jar中。resources文件夹应包含在pom文件中的中<build><resources>


使用eclipse并从IDE本身运行代码时。在单元测试中,我们如何加载Java代码中位于“ / src / test / resources”的资源。考虑一个标准的Maven项目结构。
2014年

0

以下类可用于从中加载resourceclasspath并在给定存在问题的情况下接收拟合错误消息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;
    }
}

0

我通过将/scr/main/resources文件夹添加到我的文件夹中解决了这个问题Java Build Path

在此处输入图片说明


试试这个,但这不是解决方案
Jasonw

0

我通过编写为在运行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);

您的文件结构如何?
luckydonald


0

您可以使用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()));

-2

我可以在不引用“类”或“ ClassLoader”的情况下运行它。

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

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

b)不是工作目录后代的子文件夹:projects / files / example.file

b2)另一个不是工作目录的子文件夹:program / files / 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));
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.