web-dev-qa-db-de.com

Wie man wirklich eine Textdatei aus dem Klassenpfad in Java liest

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

Ich versuche, den folgenden Eingabestream in die Datei zu laden:

Platzieren Sie das Dateiverzeichnis (D:\myDir) in CLASSPATH und versuchen Sie es wie folgt:

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

Platzieren Sie den vollständigen Dateipfad (D:\myDir\SomeTextFile.txt) in CLASSPATH und versuchen Sie es mit den obigen 3 Codezeilen.

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

344
Chaitanya MSV

Wenn sich das Verzeichnis im Klassenpfad in einer Klasse befindet, die vom selben Klassenladeprogramm geladen wurde, sollten Sie in der Lage sein, Folgendes 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 das 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 wie auf einer Linux-Box):

Java -classpath code:txt dummy.Test

Ergebnisse:

true
true
571
Jon Skeet

Bei Verwendung des Spring Frameworks (entweder als Sammlung von Dienstprogrammen oder müssen Sie die letztere Funktionalität nicht verwenden) Sie können leicht die Resource Abstraktion verwenden.

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

Über die Schnittstelle Resource können Sie auf die Ressource als InputStream , URL, URI oder File . Ändern des Ressourcentyps auf z. Bei einer Dateisystemressource handelt es sich lediglich um eine Änderung der Instanz.

114
yawn

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 bei Bedarf 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 () aufgerufen wird.

Seit Java 7 besteht eine bequeme Möglichkeit, Zeichensätze anzugeben, darin, die in Java.nio.charset.StandardCharsets definierten Konstanten zu verwenden (dies sind gemäß ihren Javadocs , "garantiert auf jeder Implementierung der Plattform Java verfügbar.").

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

51
Peter Perháč

Bitte versuche

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

Ihre Versuche haben nicht funktioniert, weil nur der Klassenlader für Ihre Klassen aus dem Klassenpfad laden kann. Sie haben das Klassenladeprogramm für das Java System selbst verwendet.

25
tangens

Um den Inhalt der Datei tatsächlich zu lesen, verwende ich gern 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);
}
20
Pavel

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

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

Irgendwie funktioniert die beste Antwort bei mir nicht. Ich muss stattdessen einen etwas anderen Code verwenden.

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

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

10
user1695166

Wenn Sie Guave verwenden:

import com.google.common.io.Resources;

wir können URL von CLASSPATH bekommen:

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

oder InputStream:

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

Um den Inhalt einer Datei aus dem classpath in einen String zu lesen, können Sie dies verwenden:

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

Hinweis:
IOUtils ist Teil von Commons IO .

Nenne es so:

_String fileContents = resourceToString("ImOnTheClasspath.txt");
_
2
BullyWiiPlaza

Sie sagen: "Ich versuche, eine Textdatei zu lesen, die in der Systemvariablen CLASSPATH festgelegt ist." Ich vermute, dies ist unter Windows und Sie verwenden diesen unschönen Dialog, um die "Systemvariablen" zu bearbeiten.

Jetzt führen Sie Ihr Programm Java in der Konsole aus. Und das funktioniert nicht: Die Konsole erhält eine Kopie der Werte der Systemvariablen einmal, wenn es gestartet ist. Dies bedeutet, dass jede Änderung im Dialog danach keine Auswirkung hat.

Es gibt diese Lösungen:

  1. Starten Sie nach jeder Änderung eine neue Konsole

  2. Verwenden Sie set CLASSPATH=... in der Konsole, um die Kopie der Variablen in der Konsole festzulegen. Wenn Ihr Code funktioniert, fügen Sie den letzten Wert in das Variablendialogfeld ein.

  3. Setzen Sie den Aufruf von Java in die Datei .BAT und doppelklicken Sie darauf. Dadurch wird jedes Mal eine neue Konsole erstellt (wodurch der aktuelle Wert der Systemvariablen kopiert wird).

ACHTUNG: Wenn Sie auch eine Benutzervariable CLASSPATH haben, wird diese Ihre Systemvariable spiegeln. Aus diesem Grund ist es in der Regel besser, den Aufruf Ihres Programms Java in eine Datei .BAT zu schreiben und dort den Klassenpfad (mithilfe von set CLASSPATH=) festzulegen, als sich auf ein globales System zu verlassen oder Benutzervariable.

Dies stellt auch sicher, dass auf Ihrem Computer mehrere Programme Java ausgeführt werden können, da diese unterschiedliche Klassenpfade haben müssen.

1
Aaron Digulla

Meine Antwort ist nicht genau das, was in der Frage gefragt wird. Vielmehr gebe ich eine Lösung an, wie einfach wir eine Datei aus unserem Projektklassenpfad in unsere Java -Anwendung einlesen können.

Angenommen, ein Konfigurationsdateiname example.xml befindet sich in einem Pfad wie dem folgenden:

com.myproject.config.dev

und unsere Java ausführbare Klassendatei befindet sich im folgenden Pfad: -

com.myproject.server.main

überprüfen Sie nun beide oben genannten Pfade. Dies ist das nächstgelegene gemeinsame Verzeichnis/der nächstgelegene gemeinsame Ordner, von dem aus Sie auf die beiden Verzeichnisse dev und main (com.myproject.server.main) zugreifen können - wo die ausführbare Klasse Java unserer Anwendung existiert) - Wir können sehen, dass myproject Ordner/Verzeichnis das nächstgelegene gemeinsame Verzeichnis/Verzeichnis ist, von dem aus wir auf unser Beispiel zugreifen können. XML-Datei. Daher müssen wir von einer ausführbaren Klasse Java im Ordner/Verzeichnis main zwei Schritte zurückgehen, wie ../../, um auf - zuzugreifen. myproject. Nun folgt, wie wir die Datei lesen können: -

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