如何真正从 Java 中的类路径读取文本文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1464291/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to really read text file from classpath in Java
提问by Chaitanya MSV
I am trying to read a text file which is set in CLASSPATH system variable. Not a user variable.
我正在尝试读取在 CLASSPATH 系统变量中设置的文本文件。不是用户变量。
I am trying to get input stream to the file as below:
我正在尝试将输入流输入文件,如下所示:
Place the directory of file (D:\myDir
)in CLASSPATH and try below:
将文件 ( 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");
Place full path of file (D:\myDir\SomeTextFile.txt
)in CLASSPATH and try the same above 3 lines of code.
将文件 ( D:\myDir\SomeTextFile.txt
) 的完整路径放在 CLASSPATH 中,然后尝试以上 3 行代码。
But unfortunately NONE of them are working and I am always getting null
into my InputStream in
.
但不幸的是,他们都没有工作,我总是null
进入我的 InputStream in
。
采纳答案by Jon Skeet
With the directory on the classpath, from a class loaded by the same classloader, you should be able to use either of:
使用类路径上的目录,从由同一类加载器加载的类,您应该能够使用:
// 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");
If those aren't working, that suggests something else is wrong.
如果这些不起作用,则表明其他地方出了问题。
So for example, take this code:
例如,拿这个代码:
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);
}
}
And this directory structure:
而这个目录结构:
code
dummy
Test.class
txt
SomeTextFile.txt
And then (using the Unix path separator as I'm on a Linux box):
然后(在 Linux 机器上使用 Unix 路径分隔符):
java -classpath code:txt dummy.Test
Results:
结果:
true
true
回答by tangens
Please try
请尝试
InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");
Your tries didn't work because only the class loader for yourclasses is able to load from the classpath. You used the class loader for the java system itself.
您的尝试无效,因为只有您的类的类加载器才能从类路径加载。您使用了 Java 系统本身的类加载器。
回答by Salandur
you have to put your 'system variable' on the java classpath.
您必须将“系统变量”放在 java 类路径上。
回答by yawn
When using the SpringFramework (either as a collection of utilities orcontainer - you do not need to use the latter functionality) you can easily use the Resourceabstraction.
使用SpringFramework 时(作为实用程序的集合或容器 - 您不需要使用后一种功能),您可以轻松使用Resource抽象。
Resource resource = new ClassPathResource("com/example/Foo.class");
Through the Resourceinterface you can access the resource as InputStream, URL, URIor File. Changing the resource type to e.g. a file system resource is a simple matter of changing the instance.
通过Resource接口,您可以以InputStream、URL、URI或File 的形式访问资源。将资源类型更改为例如文件系统资源是更改实例的简单问题。
回答by Aaron Digulla
You say "I am trying to read a text file which is set in CLASSPATH system variable." My guess this is on Windows and you are using this ugly dialog to edit the "System Variables".
您说“我正在尝试读取在 CLASSPATH 系统变量中设置的文本文件。” 我猜这是在 Windows 上,您正在使用这个丑陋的对话框来编辑“系统变量”。
Now you run your Java program in the console. And that doesn't work: The console gets a copy of the values of the system variables oncewhen it is started. This means any change in the dialog afterwardsdoesn't have any effect.
现在您在控制台中运行您的 Java 程序。这不工作:控制台获取系统变量的值的副本,一旦当它开始。这意味着此后对话框中的任何更改都不会产生任何影响。
There are these solutions:
有这些解决方案:
Start a new console after every change
Use
set CLASSPATH=...
in the console to set the copy of the variable in the console and when your code works, paste the last value into the variable dialog.Put the call to Java into
.BAT
file and double click it. This will create a new console every time (thus copying the current value of the system variable).
每次更改后启动一个新控制台
set CLASSPATH=...
在控制台中使用在控制台中设置变量的副本,当您的代码工作时,将最后一个值粘贴到变量对话框中。将调用 Java 放入
.BAT
文件并双击它。这将每次创建一个新的控制台(从而复制系统变量的当前值)。
BEWARE: If you also have a User variable CLASSPATH
then it will shadow your system variable. That is why it is usually better to put the call to your Java program into a .BAT
file and set the classpath in there (using set CLASSPATH=
) rather than relying on a global system or user variable.
注意:如果您还有一个 User 变量,CLASSPATH
那么它会影响您的系统变量。这就是为什么通常最好将 Java 程序调用放入.BAT
文件并在其中设置类路径(使用set CLASSPATH=
)而不是依赖全局系统或用户变量。
This also makes sure that you can have more than one Java program working on your computer because they are bound to have different classpaths.
这也确保您可以在您的计算机上运行多个 Java 程序,因为它们必然具有不同的类路径。
回答by webcom
To get the class absolute path try this:
要获取类绝对路径,请尝试以下操作:
String url = this.getClass().getResource("").getPath();
回答by Pavel
To actually read the contents of the file, I like using Commons IO + Spring Core. Assuming Java 8:
为了实际读取文件的内容,我喜欢使用 Commons IO + Spring Core。假设 Java 8:
try (InputStream stream = new ClassPathResource("package/resource").getInputStream()) {
IOUtils.toString(stream);
}
Alternatively:
或者:
InputStream stream = null;
try {
stream = new ClassPathResource("/log4j.xml").getInputStream();
IOUtils.toString(stream);
} finally {
IOUtils.closeQuietly(stream);
}
回答by Peter Perhá?
This is how I read all lines of a text file on my classpath, using Java 7 NIO:
这是我使用 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());
NB this is an example of how it can be done. You'll have to make improvements as necessary. This example will only work if the file is actually present on your classpath, otherwise a NullPointerException will be thrown when getResource() returns null and .toURI() is invoked on it.
请注意,这是如何完成的一个示例。您必须根据需要进行改进。此示例仅在文件实际存在于您的类路径中时才有效,否则当 getResource() 返回 null 并在其上调用 .toURI() 时将抛出 NullPointerException 。
Also, since Java 7, one convenient way of specifying character sets is to use the constants defined in java.nio.charset.StandardCharsets
(these are, according to their javadocs, "guaranteed to be available on every implementation of the Java platform.").
此外,从 Java 7 开始,指定字符集的一种方便方法是使用中定义的常量java.nio.charset.StandardCharsets
(根据它们的javadoc,这些常量“保证在 Java 平台的每个实现上都可用。”)。
Hence, if you know the encoding of the file to be UTF-8, then specify explicitly the charset StandardCharsets.UTF_8
因此,如果您知道文件的编码为 UTF-8,则明确指定字符集 StandardCharsets.UTF_8
回答by user1695166
Somehow the best answer doesn't work for me. I need to use a slightly different code instead.
不知何故,最佳答案对我不起作用。我需要使用稍微不同的代码。
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("SomeTextFile.txt");
I hope this help those who encounters the same issue.
我希望这能帮助那些遇到同样问题的人。
回答by sachinthana87
Don't use getClassLoader() method and use the "/" before the file name. "/" is very important
不要使用 getClassLoader() 方法并在文件名前使用“/”。“/“ 非常重要
this.getClass().getResourceAsStream("/SomeTextFile.txt");