ChatGPT解决这个技术问题 Extra ChatGPT

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

我的项目具有以下结构:

/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) ...也许这就是区别?

P
Paul Vargas

尝试下一个:

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
}

笔记

在 The Wayback Machine 中看到它。也在 GitHub 中。


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

尝试:

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

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

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


对于那些寻求理智的人,这篇文章将带您一路获取资源作为 String stackoverflow.com/a/35446009/544045
“/”是关键。
O
OneCricketeer

在 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 不应该关闭吗?
此答案适用于战争文件而不适用于 jar 文件。
D
Datageek

这是使用 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。人们真的应该使用不稳定类的方法吗?
f
fuat

非春季项目:

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()));

p
phray2002

对于 1.7 之后的 java

 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”(注意斜线)。
Y
Yan Khonski

我面对the same issue

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

mvn clean package

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

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


谢谢,让我免于认为我疯了!
c
ctesniere
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("test.csv");

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


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

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

scr/main/resources/calibril.ttf

https://i.stack.imgur.com/cxA6E.png

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类的全名吗?
s
shalamus

导入以下内容:

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

P
Piyush Mittal

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

B
Bhawna Joshi

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

s
sagar vyas

如果您在静态方法中加载文件,那么 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();

A
Alferd Nobel

要从 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());

J
Jorn

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


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

以下类可用于从 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;
    }
}

4
4b0
this.getClass().getClassLoader().getResource("filename").getPath()

l
linqu

即使我遵循了答案,也找不到我在测试文件夹中的文件。它通过重建项目得到解决。似乎 IntelliJ 没有自动识别新文件。很讨厌发现。


d
disizaniknem

我通过写为

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

您的文件结构如何?
A
AndreGraveler

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

假设我们有三个场景,文件'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 = new File(path);

3) 你现在可以开始了:

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