Wie liest man eine Textdatei aus Klassenpfad in Java?

Lesezeit: 7 Minuten

Benutzeravatar von Chaitanya MSV
Chaitanya MSV

Ich versuche, eine Textdatei zu lesen, die in der Systemvariablen CLASSPATH festgelegt ist. Keine Benutzervariable.

Ich versuche, den Eingabestrom wie folgt in die Datei zu bekommen:

Legen Sie das Verzeichnis der Datei (D:\myDir) in CLASSPATH und versuchen Sie es unten:

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

Geben Sie den vollständigen Pfad der Datei ein (D:\myDir\SomeTextFile.txt) in CLASSPATH und versuchen Sie dasselbe über 3 Codezeilen.

Aber leider funktioniert KEINER von ihnen und ich bekomme immer null in meinen InputStream in.

Benutzeravatar von Jon Skeet
Jon Skeet

Mit dem Verzeichnis im Klassenpfad aus einer Klasse, die von demselben Klassenlader geladen wurde, sollten Sie in der Lage sein, eines der folgenden zu verwenden:

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

Wenn diese nicht funktionieren, deutet dies darauf hin, dass etwas anderes nicht stimmt.

Nehmen Sie zum Beispiel diesen 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);
    }
}

Und diese Verzeichnisstruktur:

code
    dummy
          Test.class
txt
    SomeTextFile.txt

Und dann (unter Verwendung des Unix-Pfadtrennzeichens, da ich auf einer Linux-Box bin):

java -classpath code:txt dummy.Test

Ergebnisse:

true
true

  • Sie haben relative und absolute Pfade verwechselt. Ein Pfad, der mit “/” beginnt, ist absolut (dh beginnt mit dem, was in CLASSPATH aufgeführt ist). Alle anderen Pfade sind relativ zum Paket der Klasse, die Sie aufrufen getResourceAsStream()

    – Aaron Digulla

    23. September 2009 um 7:25 Uhr

  • Nein du Pleite mein beispiel. Ich werde die Kommentare bearbeiten, um sie klarer zu machen, aber der Punkt ist, dass bei Verwendung von ClassLoader alle Pfade bereits als absolut angenommen werden. Es gibt nichts, womit sie relativ sein könnten.

    – Jon Skeet

    23. September 2009 um 7:57 Uhr

  • Verwenden Sie auch nicht Java.IO.File.Separator. Unter Windows funktioniert es nicht. Wenn Sie diesen Code unter Windows ausführen, muss er immer noch ‘/’ und nicht ‘\’ sein.

    – Pradhan

    14. Juni 2013 um 17:56 Uhr

  • @Pradhan: Nein, das solltest du nicht verwenden File.Separator – weil Sie nicht nach a fragen Dateidu fragst nach a Ressource. Es ist wichtig zu verstehen, dass die betreffende Abstraktion nicht das Dateisystem ist.

    – Jon Skeet

    14. Juni 2013 um 17:59 Uhr

  • @jagdpanzer: Nun, es ist im Grunde nur für Klassen, die vom selben Classloader geladen werden – und das liegt daran Class.getResourceAsStream ist wirklich eine bequeme Methode zum Anrufen ClassLoader.getResourceAsStream, aber mit der zusätzlichen Eigenschaft “relativer” Ressourcen. Wenn Sie eine absolute Ressource angeben, wird jeder Aufruf, der denselben Classloader verwendet, dasselbe tun.

    – Jon Skeet

    5. November 2015 um 18:07 Uhr

Bei Verwendung der Feder Framework (entweder als Sammlung von Dienstprogrammen oder container – Sie müssen die letztere Funktionalität nicht verwenden) können Sie einfach verwenden Ressource Abstraktion.

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

Durch das Ressource Schnittstelle können Sie auf die Ressource zugreifen Eingabestrom, URL, URI oder Datei. Das Ändern des Ressourcentyps zu zB einer Dateisystemressource ist eine einfache Sache der Änderung der Instanz.

  • Könnten Sie bitte einen Beispielcode bereitstellen, wie dies in der Datei-E/A verwendet werden kann? Ich kann keine finden anständig, explizit und einfach Art und Weise, wie man es im Internet verwendet :((((

    Benutzer1685185

    11. Februar 2014 um 16:00 Uhr

  • Klappt wunderbar. Der mitgelieferte One Liner ist alles, was Sie brauchen. Verwenden Sie das Stream-Parsing aus anderen Beispielen, wenn Sie nicht wissen, wie Sie eine Zeichenfolge aus dem Stream erhalten.

    – Josef Lust

    16. Februar 2014 um 18:14 Uhr

  • Ich hatte auch ein paar Probleme damit, genau herauszufinden, was ich mit der Ressource-Variablen machen sollte. Ich habe die Antwort etwas detaillierter bearbeitet

    – DavidZemon

    2. Dezember 2014 um 14:10 Uhr

  • Ich habe Spring bereits verwendet und den “reinen Java” -Weg ausprobiert. Es hat mich umgebracht, die Unterschiede zwischen getResource, getResourceAsStream usw. ohne gute Arbeitsbeispiele. Dies ist ein perfektes Beispiel für Kapselung, also muss ich mich nicht darum kümmern.

    – TinkerTenorSoftwareGuy

    19. Januar 2017 um 16:08 Uhr

  • Seien Sie vorsichtig, wenn Sie Ihr Projekt in ein JAR packen, sollten Sie einen InputStream verwenden. Wenn Sie eine Datei verwenden, funktioniert sie in Ihrer IDE, schlägt jedoch fehl, wenn Sie sie aus dem JAR testen. Wenn Sie wirklich eine Datei benötigen, versuchen Sie es mit stackoverflow.com/questions/4317035/…

    – Rafael Membrives

    30. August 2017 um 7:40 Uhr

Benutzeravatar von Peter Perháč
Peter Perhač

So lese ich alle Zeilen einer Textdatei in meinem Klassenpfad mit 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: Dies ist ein Beispiel dafür, wie es gemacht werden kann. Sie müssen gegebenenfalls Verbesserungen vornehmen. Dieses Beispiel funktioniert nur, wenn die Datei tatsächlich in Ihrem Klassenpfad vorhanden ist, andernfalls wird eine NullPointerException ausgelöst, wenn getResource() null zurückgibt und .toURI() dafür aufgerufen wird.

Seit Java 7 besteht eine bequeme Möglichkeit zum Angeben von Zeichensätzen darin, die in definierten Konstanten zu verwenden java.nio.charset.StandardCharsets
(diese sind laut ihrer Javadocs“garantiert auf jeder Implementierung der Java-Plattform verfügbar zu sein.”).

Wenn Sie also wissen, dass die Codierung der Datei UTF-8 ist, geben Sie den Zeichensatz explizit an StandardCharsets.UTF_8

  • Vielen Dank für die NIO-Lösung – es ist eine Schande, dass so wenige Leute diese großartige API verwenden.

    – mvreijn

    14. April 2015 um 18:50 Uhr

  • Versuchen Sie, in einen einzelnen String einzulesen. new String(Files.readAllBytes(Paths.get(MyClass.class.getResource(resource).toURI())));

    – Theo Briskoe

    23. Juli 2016 um 12:03 Uhr

  • Beste Lösung für mich, da es keine Abhängigkeiten wie Spring oder Commons IO benötigt.

    – Bernie

    25. September 2016 um 9:44 Uhr

  • Dies schlägt fehl, wenn sich Ihre Ressourcendatei in einem JAR befindet, z. B. einem Maven-Modul. In diesem Fall müssen Sie etwas wie verwenden Spring‘s StreamUtils.copyToString.

    – Somu

    14. Februar 2020 um 9:33 Uhr

Bitte versuche

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

Ihre Versuche haben nicht funktioniert, weil nur der Klassenlader für dein Klassen können aus dem Klassenpfad geladen werden. Sie haben den Klassenlader für das Java-System selbst verwendet.

Benutzeravatar von Pavel
Pavel

Um den Inhalt der Datei tatsächlich zu lesen, verwende ich gerne Commons IO + Spring Core. Angenommen Java 8:

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

Alternative:

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

  • Was ist mit dem Schließen des Inputstreams?

    – Stefan

    21. April 2016 um 15:32 Uhr

  • Der Stream wird automatisch geschlossen. Es ist eine Funktion von Java 7 “Versuchen Sie es mit Ressourcen” docs.oracle.com/javase/tutorial/essential/exceptions/…

    – Michał Maciej Gałuszka

    13. September 2018 um 6:58 Uhr

  • Nur wenn es innerhalb der try-Anweisung steht, was hier nicht der Fall ist. Es hätte try (final InputStream stream = new ClassPathResource(“/log4j.xml”).getInputStream()) {…

    – bzw

    13. Mai 2019 um 13:23 Uhr

Benutzeravatar von 5agado
5Agado

Um den absoluten Pfad der Klasse zu erhalten, versuchen Sie Folgendes:

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

  • Was ist mit dem Schließen des Inputstreams?

    – Stefan

    21. April 2016 um 15:32 Uhr

  • Der Stream wird automatisch geschlossen. Es ist eine Funktion von Java 7 “Versuchen Sie es mit Ressourcen” docs.oracle.com/javase/tutorial/essential/exceptions/…

    – Michał Maciej Gałuszka

    13. September 2018 um 6:58 Uhr

  • Nur wenn es innerhalb der try-Anweisung steht, was hier nicht der Fall ist. Es hätte try (final InputStream stream = new ClassPathResource(“/log4j.xml”).getInputStream()) {…

    – bzw

    13. Mai 2019 um 13:23 Uhr

Benutzeravatar von user1695166
Benutzer1695166

Irgendwie funktioniert die beste Antwort nicht für mich. Ich muss stattdessen einen etwas anderen Code verwenden.

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

Ich hoffe, dies hilft denen, die auf das gleiche Problem stoßen.

  • Dies hat mir auch auf Android geholfen, wo eine Klasse vom Anwendungslader geladen wurde, aber ein Schlüssel, den sie benötigte, im UI-Thread faul geladen wurde.

    – asokan

    4. Juli 2016 um 22:35 Uhr

  • Sie müssen angeben, warum die beste Antwort für Sie nicht funktioniert (z. B. die Struktur Ihrer Anwendung, das von Ihnen verwendete Framework, der Fehler usw.). Die beste Antwort lautete eindeutig, dass 1) das Verzeichnis im Klassenpfad sein muss, 2) Sie eine Anfrage von einer Klasse stellen müssen, die von demselben Klassenlader geladen wurde. Es besteht die Möglichkeit, dass eine dieser Annahmen für Ihre Anwendung nicht zutrifft. Auch der Context Class Loader ist sehr entmutigt, da er als Hack eingeführt wurde. Einige Frameworks nutzen es, aber es ist wichtig, die Auswirkungen zu kennen (was erfordert, dass Sie den Hintergrund Ihres Projekts beschreiben).

    – Xinchao

    20. Juli 2018 um 6:43 Uhr

  • Dies funktioniert in einem statischen Kontext (im Gegensatz zu anderen hier erwähnten Lösungen).

    – Witali Sasanowitsch

    21. Juni 2021 um 20:17 Uhr

1436860cookie-checkWie liest man eine Textdatei aus Klassenpfad in Java?

This website is using cookies to improve the user-friendliness. You agree by using the website further.

Privacy policy