如何在Java中从classpath中真正读取文本文件

Cha*_*MSV 349 java classpath

我正在尝试读取在CLASSPATH系统变量中设置的文本文件.不是用户变量.

我试图获取输入流到文件,如下所示:

将file(D:\myDir)的目录放在CLASSPATH中并尝试以下操作:

InputStream in = this.getClass().getClassLoader().getResourceAsStream("SomeTextFile.txt");
InputStream in = this.getClass().getClassLoader().getResourceAsStream("/SomeTextFile.txt");
InputStream in = this.getClass().getClassLoader().getResourceAsStream("//SomeTextFile.txt");
Run Code Online (Sandbox Code Playgroud)

将文件(D:\myDir\SomeTextFile.txt)的完整路径放在CLASSPATH中,并尝试上面3行代码.

但不幸的是,他们中的任何人都在工作,我总是null进入我的InputStream in.

Jon*_*eet 579

使用类路径上的目录,从同一个类加载器加载的类,您应该能够使用以下任何一个:

// From ClassLoader, all paths are "absolute" already - there's no context
// from which they could be relative. Therefore you don't need a leading slash.
InputStream in = this.getClass().getClassLoader()
                                .getResourceAsStream("SomeTextFile.txt");
// From Class, the path is relative to the package of the class unless
// you include a leading slash, so if you don't want to use the current
// package, include a slash like this:
InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");
Run Code Online (Sandbox Code Playgroud)

如果那些不起作用,那表明还有其他问题.

例如,请使用以下代码:

package dummy;

import java.io.*;

public class Test
{
    public static void main(String[] args)
    {
        InputStream stream = Test.class.getResourceAsStream("/SomeTextFile.txt");
        System.out.println(stream != null);
        stream = Test.class.getClassLoader().getResourceAsStream("SomeTextFile.txt");
        System.out.println(stream != null);
    }
}
Run Code Online (Sandbox Code Playgroud)

而这个目录结构:

code
    dummy
          Test.class
txt
    SomeTextFile.txt
Run Code Online (Sandbox Code Playgroud)

然后(使用Unix路径分隔符,因为我在Linux机器上):

java -classpath code:txt dummy.Test
Run Code Online (Sandbox Code Playgroud)

结果:

true
true
Run Code Online (Sandbox Code Playgroud)

  • @Pradhan:不,你不应该使用`File.Separator` - 因为你没有要求*文件*,你要求*资源*.重要的是要理解所涉及的抽象不是文件系统. (27认同)
  • 不,你打破了我的榜样.我将编辑注释以使它们更清晰,但重点是使用ClassLoader所有路径都被认为是绝对的.他们没有什么可以相对的. (12认同)
  • 也不要使用Java.IO.File.Separator.它不会在Windows上工作.如果您在Windows上运行此代码,它仍然必须是'/'而不是'\' (6认同)
  • 你混合了相对和绝对路径.以"/"开头的路径是绝对路径(即从CLASSPATH中列出的任何内容开始).所有其他路径都相对于您调用`getResourceAsStream()`的类的包 (2认同)

yaw*_*awn 114

使用Spring Framework时(作为实用程序容器的集合- 您不需要使用后者的功能),您可以轻松使用Resource抽象.

Resource resource = new ClassPathResource("com/example/Foo.class");
Run Code Online (Sandbox Code Playgroud)

通过Resource接口,您可以将资源作为InputStream,URL,URIFile访问.将资源类型更改为例如文件系统资源是更改实例的简单问题.

  • 您能否提供一个示例代码,说明如何在文件I/O中使用它?关于如何在互联网上使用它,我找不到_decent_,_explicit_和_straightforward_方式:(((( (4认同)
  • 请注意,如果您将项目打包到 jar 中,则应使用 InputStream。如果您使用文件,它可以在您的 IDE 中工作,但如果您从 jar 中测试它,则会失败。如果您真的需要文件,请尝试使用 /sf/ask/302192481/ (2认同)

Pet*_*háč 52

这就是我使用Java 7 NIO读取类路径上文本文件的所有行的方法:

...
import java.nio.charset.Charset;
import java.nio.file.Files;
import java.nio.file.Paths;

...

Files.readAllLines(
    Paths.get(this.getClass().getResource("res.txt").toURI()), Charset.defaultCharset());
Run Code Online (Sandbox Code Playgroud)

注意,这是一个如何完成它的例子.你必须根据需要进行改进.此示例仅在文件实际存在于类路径中时才有效,否则当getResource()返回null并且在其上调用.toURI()时,将抛出NullPointerException.

此外,从Java 7开始,指定字符集的一种便捷方法是使用定义的常量java.nio.charset.StandardCharsets (根据它们的javadoc,"保证在Java平台的每个实现上都可用.").

因此,如果您知道文件的编码为UTF-8,则明确指定charset StandardCharsets.UTF_8

  • 要读入单个字符串尝试.new String(Files.readAllBytes(Paths.get(MyClass.class.getResource(resource).toURI()))); (7认同)
  • 如果您的资源文件位于 jar 内(例如 Maven 模块),则此操作将会失败。在这种情况下,您需要使用诸如“Spring”的“StreamUtils.copyToString”之类的东西。 (4认同)
  • 对我来说最好的解决方案,因为它不需要任何依赖项,如 Spring 或 Commons IO。 (2认同)

tan*_*ens 25

请试试

InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");
Run Code Online (Sandbox Code Playgroud)

您尝试没有成功,因为只对类加载器类是能够从classpath加载.您使用了类加载器来为java系统本身.

  • 如果您使用它而没有"/",那么您正在"this"包中查找您的文件. (3认同)

Pav*_*vel 20

要实际读取文件的内容,我喜欢使用Commons IO + Spring Core.假设Java 8:

try (InputStream stream = new ClassPathResource("package/resource").getInputStream()) {
    IOUtils.toString(stream);
}
Run Code Online (Sandbox Code Playgroud)

或者:

InputStream stream = null;
try {
    stream = new ClassPathResource("/log4j.xml").getInputStream();
    IOUtils.toString(stream);
} finally {
    IOUtils.closeQuietly(stream);
}
Run Code Online (Sandbox Code Playgroud)

  • 仅当它位于 try 语句内部时,这里不是这种情况。应该尝试 (final InputStream stream = new ClassPathResource("/log4j.xml").getInputStream()) {... (2认同)

小智 15

要获得类绝对路径,请尝试以下操作:

String url = this.getClass().getResource("").getPath();
Run Code Online (Sandbox Code Playgroud)


use*_*166 10

不知何故,最好的答案对我不起作用.我需要使用稍微不同的代码.

ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("SomeTextFile.txt");
Run Code Online (Sandbox Code Playgroud)

我希望这可以帮助那些遇到同样问题的人.


Ale*_*nov 6

如果你使用番石榴:

import com.google.common.io.Resources;
Run Code Online (Sandbox Code Playgroud)

我们可以从CLASSPATH获取URL:

URL resource = Resources.getResource("test.txt");
String file = resource.getFile();   // get file path 
Run Code Online (Sandbox Code Playgroud)

或InputStream:

InputStream is = Resources.getResource("test.txt").openStream();
Run Code Online (Sandbox Code Playgroud)