Wie liest man eine Textdatei aus Klassenpfad in Java?
Lesezeit: 7 Minuten
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.
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
Peter Perhač
So lese ich alle Zeilen einer Textdatei in meinem Klassenpfad mit Java 7 NIO:
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.
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);
}
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
5Agado
Um den absoluten Pfad der Klasse zu erhalten, versuchen Sie Folgendes:
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
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
14368600cookie-checkWie liest man eine Textdatei aus Klassenpfad in Java?yes