如何从Java中的类路径真正读取文本文件


366

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

我正在尝试将输入流传输到文件,如下所示:

将文件(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");

将文件(D:\myDir\SomeTextFile.txt)的完整路径放在CLASSPATH中,然后尝试上述3行代码中的相同路径。

但是不幸的是,它们都没有起作用,我一直都在null进入InputStream in

Answers:


605

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

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

如果这些都不起作用,则表明还有其他问题。

因此,例如,使用以下代码:

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

而这个目录结构:

code
    dummy
          Test.class
txt
    SomeTextFile.txt

然后(像在Linux上一样使用Unix路径分隔符):

java -classpath code:txt dummy.Test

结果:

true
true

2
您混合了相对路径和绝对路径。以“ /”开头的路径是绝对路径(即从CLASSPATH中列出的任何内容开始)。所有其他路径均与您要调用的课程的课程包相关getResourceAsStream()
Aaron Digulla 09年

13
不,你打破了我的榜样。我将编辑注释以使它们更清晰,但要点是,使用ClassLoader假定所有路径都是绝对路径。他们没有什么可相对的。
乔恩·斯基特

6
也不要使用Java.IO.File.Separator。它不会在Windows上工作。如果您在Windows上运行此代码,它仍然必须是'/'而不是'\'
Pradhan

28
@Pradhan:不,您不应该使用File.Separator-因为您不要求文件,而是要资源。重要的是要了解所涉及的抽象不是文件系统。
乔恩·斯基特

1
@jagdpanzer:好吧,基本上,这仅适用于由同一类加载器加载的类-这是因为Class.getResourceAsStream它确实是一种方便的调用方法ClassLoader.getResourceAsStream,但具有“相对”资源的附加功能。如果您指定绝对资源,则使用相同类加载器的任何调用都将执行相同的操作。
乔恩·斯基特

115

使用Spring Framework时(作为实用程序的集合容器 -无需使用后一种功能),您可以轻松地使用Resource抽象。

Resource resource = new ClassPathResource("com/example/Foo.class");

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


6
您能否提供一个示例代码,说明如何在文件I / O中使用它?我找不到如何在互联网上使用它的体面明确直接的方法:((((

奇迹般有效。提供的一根衬管就是您所需要的。如果您不知道如何从流中获取字符串,请使用其他示例中的流解析。
Joseph Lust 2014年

我也很难弄清楚该如何处理资源变量。我已经更详细地编辑了答案
DavidZemon 2014年

我已经在使用Spring并尝试“纯java”方式。没什么好用的例子,这真让我难受,getResource,getResourceAsStream等之间的差异。这是封装的完美示例,因此我不必在意。
TinkerTenorSoftwareGuy

1
注意,如果将项目打包到jar中,则应使用InputStream。如果使用文件,则它可以在IDE中运行,但如果从jar中测试它,则将失败。如果你真的需要一个文件尝试stackoverflow.com/questions/4317035/...
拉斐尔Membrives

58

这就是我使用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());

注意:这是如何完成此操作的示例。您必须根据需要进行改进。此示例仅在文件实际存在于类路径中时才起作用,否则,当getResource()返回null并在其上调用.toURI()时,将引发NullPointerException。

另外,自Java 7起,一种指定字符集的简便方法是使用中定义的常量java.nio.charset.StandardCharsets (根据其javadocs, “保证在Java平台的每个实现中都可用”)。

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


1
感谢您提供的NIO解决方案-很少有人使用这个出色的API,实在可惜。
mvreijn 2015年

7
要读入单个String,请尝试。新的String(Files.readAllBytes(Paths.get(MyClass.class.getResource(resource).toURI())));
西奥·布里斯科

2
对我来说是最好的解决方案,因为它不需要任何依赖,例如Spring或Commons IO。
伯尼

1
如果您的资源文件位于jar内(例如maven模块),则此操作将失败。在这种情况下,您需要使用类似SpringStreamUtils.copyToString
索姆

26

请试试

InputStream in = this.getClass().getResourceAsStream("/SomeTextFile.txt");

您的尝试没有用,因为只有您的类的类加载器才能从类路径加载。您为Java系统本身使用了类加载器。


虽然不确定“ /”。在这种情况下,相对路径可能会更好。
VonC

3
如果不带“ /”使用它,则在“ this”包中查找文件。
tangens

1
InputStream文件= this.getClass()。getResourceAsStream(“ SomeTextFile.txt”); InputStream文件= this.getClass()。getResourceAsStream(“ / SomeTextFile.txt”); InputStream文件= this.getClass()。getResourceAsStream(“ // SomeTextFile.txt”); 以上方法均
无效

@Chaitanya:您可以根据John Skeet的答案来运行示例吗?
亚伦·迪古拉09年


20

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

try (InputStream stream = new ClassPathResource("package/resource").getInputStream()) {
    IOUtils.toString(stream);
}

或者:

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

关闭输入流呢?
Stephan

流将自动关闭。它是Java 7中的一项功能“尝试与资源” docs.oracle.com/javase/tutorial/essential/exceptions/...
米哈尔马切伊Gałuszka

仅当它位于try语句中时,此处不是这种情况。应该尝试一下(最终InputStream流= new ClassPathResource(“ / log4j.xml”)。getInputStream()){...
andresp '19

15

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

String url = this.getClass().getResource("").getPath();

然后什么?该信息本身是没有用的。
罗恩侯爵

此信息是完美的。我只是想念getPath()!
Patrick

@Patrick此答案不提供“类绝对路径”。它提供一个URL。完全不一样。
罗恩侯爵

12

不知何故,最佳答案对我不起作用。我需要使用稍微不同的代码来代替。

ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("SomeTextFile.txt");

希望这对遇到相同问题的人有所帮助。


这也对我在Android上的应用程序加载器加载了类的Android有所帮助,但是所需的键却是在UI线程中延迟加载的。
asokan

您需要提供有关为什么最佳答案不适合您的信息(例如,应用程序的结构,所使用的框架,错误等)。最好的答案清楚地表明:1)目录必须位于类路径上,2)您需要从同一类加载器加载的类中请求。这些假设可能不适合您的应用。另外,由于上下文类加载器是作为一种hacker引入的,因此非常不鼓励使用。某些框架确实使用了它,但重要的是要知道其含义(这需要您描述项目的背景)
Xinchao

6

如果您使用番石榴:

import com.google.common.io.Resources;

我们可以从CLASSPATH获取URL:

URL resource = Resources.getResource("test.txt");
String file = resource.getFile();   // get file path 

或InputStream:

InputStream is = Resources.getResource("test.txt").openStream();

如果资源位于JAR或WAR文件中,则文件路径没有任何用处。
罗恩侯爵

URL的getFile方法不返回文件名。它仅返回URL的路径部分,不能保证它是有效的文件名。(URL类是Java 1.0的一部分;那时,大多数URL实际上都引用同一台计算机或另一台计算机上的物理文件。)
VGR

3

要将文件的内容从中读取为字符串classpath,可以使用以下命令:

private String resourceToString(String filePath) throws IOException, URISyntaxException
{
    try (InputStream inputStream = this.getClass().getClassLoader().getResourceAsStream(filePath))
    {
        return IOUtils.toString(inputStream);
    }
}

注意:
IOUtils是的一部分Commons IO

这样称呼它:

String fileContents = resourceToString("ImOnTheClasspath.txt");

1

您说:“我正在尝试读取在CLASSPATH系统变量中设置的文本文件。” 我猜这是在Windows上,您正在使用此丑陋的对话框来编辑“系统变量”。

现在,您可以在控制台中运行Java程序。那是行不通的:控制台在启动时会获得一次系统变量值的副本。这意味着之后对话框中的任何更改均无效。

有以下解决方案:

  1. 每次更改后启动新控制台

  2. set CLASSPATH=...在控制台中使用,以在控制台中设置变量的副本,并在代码工作时将最后一个值粘贴到变量对话框中。

  3. 将对Java的调用放入.BAT文件中,然后双击它。每次都会创建一个新的控制台(从而复制系统变量的当前值)。

注意:如果您还有一个User变量,CLASSPATH那么它将隐藏您的系统变量。这就是为什么通常最好将对Java程序的调用放入.BAT文件中并在其中设置类路径(使用set CLASSPATH=),而不要依赖于全局系统或用户变量。

这还可以确保您可以在计算机上运行多个Java程序,因为它们必然具有不同的类路径。


0

我的答案不完全是问题中要问的内容。确切地说,我正在提供一种解决方案,确切地讲,我们可以很容易地从项目类路径将文件读取到Java应用程序中。

例如,假设配置文件名为example.xml位于如下所示的路径中:

com.myproject.config.dev

并且我们的java可执行类文件在以下路径中:

com.myproject.server.main

现在,只需检查以上路径,这是您可以从其中访问dev目录/文件夹(com.myproject.server.main-应用程序的Java可执行文件所在的位置)的最近的公用目录/文件夹–我们可以看到那是myproject文件夹/目录,它是我们可以访问example.xml文件的最近的公用目录/文件夹。因此,从驻留在文件夹/目录main中的java可执行类开始,我们必须返回两个步骤,如../../,以访问myproject。接下来,请看我们如何读取文件:-

package com.myproject.server.main;

class Example {

  File xmlFile;

  public Example(){
       String filePath = this.getClass().getResource("../../config/dev/example.xml").getPath();
       this.xmlFile = new File(filePath);
    }

  public File getXMLFile() {
      return this.xmlFile;
  }
   public static void main(String args[]){
      Example ex = new Example();
      File xmlFile = ex.getXMLFile();
   }
}

0

如果您在jar文件中编译项目,则可以:将文件放在resources / files / your_file.text或pdf中;

并使用以下代码:

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.*;

public class readFileService(){
    private static final Logger LOGGER = LoggerFactory.getLogger(readFileService.class);


    public byte[] getFile(){
        String filePath="/files/your_file";
        InputStream inputStreamFile;
        byte[] bytes;
        try{
            inputStreamFile = this.getClass().getResourceAsStream(filePath);
            bytes = new byte[inputStreamFile.available()];
            inputStreamFile.read(bytes);    
        } catch(NullPointerException | IOException e) {
            LOGGER.error("Erreur read file "+filePath+" error message :" +e.getMessage());
            return null;
        }
        return bytes;
    } 
}

-1

我正在使用webshpere应用程序服务器,并且我的Web模块基于Spring MVC构建。的Test.properties位于资源文件夹中,我尝试使用以下方法加载此文件:

  1. this.getClass().getClassLoader().getResourceAsStream("Test.properties");
  2. this.getClass().getResourceAsStream("/Test.properties");

以上代码均未加载文件。

但是借助以下代码,该属性文件已成功加载:

Thread.currentThread().getContextClassLoader().getResourceAsStream("Test.properties");

感谢用户“ user1695166”


1
欢迎使用Stack Overflow!即使您还部分提供了解决方案的进展,也请不要添加“感谢”作为答案,如果您的解决方案与另一篇文章相同,则无需添加。在网站上花了一些时间后,您将获得足够的特权来投票赞成您喜欢的答案,这是Stack Overflow表示感谢的方式。
SuperBiasedMan 2015年

-1

采用 org.apache.commons.io.FileUtils.readFileToString(new File("src/test/resources/sample-data/fileName.txt"));


不应使用对src的引用...在最终工件中不起作用。
L. Holanda '18

-1

场景:

1)client-service-1.0-SNAPSHOT.jar有依赖性read-classpath-resource-1.0-SNAPSHOT.jar

2)我们要读取的类路径资源的内容(sample.txt)的read-classpath-resource-1.0-SNAPSHOT.jar通过client-service-1.0-SNAPSHOT.jar

3)read-classpath-resource-1.0-SNAPSHOT.jarsrc/main/resources/sample.txt

这是我准备的工作示例代码,在2-3天浪费了我的开发时间之后,我找到了完整的端到端解决方案,希望这可以帮助您节省时间

1. pom.xmlread-classpath-resource-1.0-SNAPSHOT.jar

<?xml version="1.0" encoding="UTF-8"?>
        <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
            <modelVersion>4.0.0</modelVersion>
            <groupId>jar-classpath-resource</groupId>
            <artifactId>read-classpath-resource</artifactId>
            <version>1.0-SNAPSHOT</version>
            <name>classpath-test</name>
            <properties>
                <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
                <org.springframework.version>4.3.3.RELEASE</org.springframework.version>
                <mvn.release.plugin>2.5.1</mvn.release.plugin>
                <output.path>${project.artifactId}</output.path>
                <io.dropwizard.version>1.0.3</io.dropwizard.version>
                <commons-io.verion>2.4</commons-io.verion>
            </properties>
            <dependencies>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-core</artifactId>
                    <version>${org.springframework.version}</version>
                </dependency>
                <dependency>
                    <groupId>org.springframework</groupId>
                    <artifactId>spring-context</artifactId>
                    <version>${org.springframework.version}</version>
                </dependency>
                <dependency>
                    <groupId>commons-io</groupId>
                    <artifactId>commons-io</artifactId>
                    <version>${commons-io.verion}</version>
                </dependency>
            </dependencies>
            <build>
                <resources>
                    <resource>
                        <directory>src/main/resources</directory>
                    </resource>
                </resources>
                <plugins>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-release-plugin</artifactId>
                        <version>${mvn.release.plugin}</version>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-compiler-plugin</artifactId>
                        <version>3.1</version>
                        <configuration>
                            <source>1.8</source>
                            <target>1.8</target>
                            <encoding>UTF-8</encoding>
                        </configuration>
                    </plugin>
                    <plugin>
                        <artifactId>maven-jar-plugin</artifactId>
                        <version>2.5</version>
                        <configuration>
                            <outputDirectory>${project.build.directory}/lib</outputDirectory>
                            <archive>
                                <manifest>
                                    <addClasspath>true</addClasspath>
                                    <useUniqueVersions>false</useUniqueVersions>
                                    <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                                    <mainClass>demo.read.classpath.resources.ClassPathResourceReadTest</mainClass>
                                </manifest>
                                <manifestEntries>
                                    <Implementation-Artifact-Id>${project.artifactId}</Implementation-Artifact-Id>
                                    <Class-Path>sample.txt</Class-Path>
                                </manifestEntries>
                            </archive>
                        </configuration>
                    </plugin>
                    <plugin>
                        <groupId>org.apache.maven.plugins</groupId>
                        <artifactId>maven-shade-plugin</artifactId>
                        <version>2.2</version>
                        <configuration>
                            <createDependencyReducedPom>false</createDependencyReducedPom>
                            <filters>
                                <filter>
                                    <artifact>*:*</artifact>
                                    <excludes>
                                        <exclude>META-INF/*.SF</exclude>
                                        <exclude>META-INF/*.DSA</exclude>
                                        <exclude>META-INF/*.RSA</exclude>
                                    </excludes>
                                </filter>
                            </filters>
                        </configuration>
                        <executions>
                            <execution>
                                <phase>package</phase>
                                <goals>
                                    <goal>shade</goal>
                                </goals>
                                <configuration>
                                    <transformers>
                                        <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                                        <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                            <mainClass>demo.read.classpath.resources.ClassPathResourceReadTest</mainClass>
                                        </transformer>
                                    </transformers>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>
        </project>

2. ClassPathResourceReadTest.javaclass中read-classpath-resource-1.0-SNAPSHOT.jar加载类路径资源文件的内容。

package demo.read.classpath.resources;

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

public final class ClassPathResourceReadTest {
    public ClassPathResourceReadTest() throws IOException {
        InputStream inputStream = getClass().getResourceAsStream("/sample.txt");
        BufferedReader reader = new BufferedReader(new InputStreamReader(inputStream));
        List<Object> list = new ArrayList<>();
        String line;
        while ((line = reader.readLine()) != null) {
            list.add(line);
        }
        for (Object s1: list) {
            System.out.println("@@@ " +s1);
        }
        System.out.println("getClass().getResourceAsStream('/sample.txt') lines: "+list.size());
    }
}

3. pom.xmlclient-service-1.0-SNAPSHOT.jar

<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <modelVersion>4.0.0</modelVersion>

    <groupId>client-service</groupId>
    <artifactId>client-service</artifactId>
    <version>1.0-SNAPSHOT</version>

    <dependencies>
        <dependency>
            <groupId>jar-classpath-resource</groupId>
            <artifactId>read-classpath-resource</artifactId>
            <version>1.0-SNAPSHOT</version>
        </dependency>
    </dependencies>

    <build>
        <plugins>
            <plugin>
                <artifactId>maven-jar-plugin</artifactId>
                <version>2.5</version>
                <configuration>
                    <outputDirectory>${project.build.directory}/lib</outputDirectory>
                    <archive>
                        <manifest>
                            <addClasspath>true</addClasspath>
                            <useUniqueVersions>false</useUniqueVersions>
                            <addDefaultImplementationEntries>true</addDefaultImplementationEntries>
                            <mainClass>com.crazy.issue.client.AccessClassPathResource</mainClass>
                        </manifest>
                        <manifestEntries>
                            <Implementation-Artifact-Id>${project.artifactId}</Implementation-Artifact-Id>
                            <Implementation-Source-SHA>${buildNumber}</Implementation-Source-SHA>
                            <Class-Path>sample.txt</Class-Path>
                        </manifestEntries>
                    </archive>
                </configuration>
            </plugin>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-shade-plugin</artifactId>
                <version>2.2</version>
                <configuration>
                    <createDependencyReducedPom>false</createDependencyReducedPom>
                    <filters>
                        <filter>
                            <artifact>*:*</artifact>
                            <excludes>
                                <exclude>META-INF/*.SF</exclude>
                                <exclude>META-INF/*.DSA</exclude>
                                <exclude>META-INF/*.RSA</exclude>
                            </excludes>
                        </filter>
                    </filters>
                </configuration>
                <executions>
                    <execution>
                        <phase>package</phase>
                        <goals>
                            <goal>shade</goal>
                        </goals>
                        <configuration>
                            <transformers>
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ServicesResourceTransformer" />
                                <transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
                                    <mainClass>com.crazy.issue.client.AccessClassPathResource</mainClass>
                                </transformer>
                            </transformers>
                        </configuration>
                    </execution>
                </executions>
            </plugin>
        </plugins>
    </build>
</project>

4. 在哪里AccessClassPathResource.java实例化ClassPathResourceReadTest.java类,它也将加载sample.txt并打印其内容。

package com.crazy.issue.client;

import demo.read.classpath.resources.ClassPathResourceReadTest;
import java.io.IOException;

public class AccessClassPathResource {
    public static void main(String[] args) throws IOException {
        ClassPathResourceReadTest test = new ClassPathResourceReadTest();
    }
}

5,运行可执行jar,如下所示:

[ravibeli@localhost lib]$ java -jar client-service-1.0-SNAPSHOT.jar
****************************************
I am in resources directory of read-classpath-resource-1.0-SNAPSHOT.jar
****************************************
3) getClass().getResourceAsStream('/sample.txt'): 3

-2

不要使用getClassLoader()方法,并在文件名前使用“ /”。“/“ 非常重要

this.getClass().getResourceAsStream("/SomeTextFile.txt");

使用引线/具有与使用getClassLoader()方法完全相同的效果。
罗恩侯爵

-4
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.io.IOException;

public class ReadFile

{
    /**
     * * feel free to make any modification I have have been here so I feel you
     * * * @param args * @throws InterruptedException
     */

    public static void main(String[] args) throws InterruptedException {
        // thread pool of 10
        File dir = new File(".");
        // read file from same directory as source //
        if (dir.isDirectory()) {
            File[] files = dir.listFiles();
            for (File file : files) {
                // if you wanna read file name with txt files
                if (file.getName().contains("txt")) {
                    System.out.println(file.getName());
                }

                // if you want to open text file and read each line then
                if (file.getName().contains("txt")) {
                    try {
                        // FileReader reads text files in the default encoding.
                        FileReader fileReader = new FileReader(
                                file.getAbsolutePath());
                        // Always wrap FileReader in BufferedReader.
                        BufferedReader bufferedReader = new BufferedReader(
                                fileReader);
                        String line;
                        // get file details and get info you need.
                        while ((line = bufferedReader.readLine()) != null) {
                            System.out.println(line);
                            // here you can say...
                            // System.out.println(line.substring(0, 10)); this
                            // prints from 0 to 10 indext
                        }
                    } catch (FileNotFoundException ex) {
                        System.out.println("Unable to open file '"
                                + file.getName() + "'");
                    } catch (IOException ex) {
                        System.out.println("Error reading file '"
                                + file.getName() + "'");
                        // Or we could just do this:
                        ex.printStackTrace();
                    }
                }
            }
        }

    }

}

不会以任何方式回答问题。
罗恩侯爵,2015年

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.