web-dev-qa-db-fra.com

Comment vraiment lire un fichier texte depuis classpath dans Java

J'essaie de lire un fichier texte défini dans la variable système CLASSPATH. Pas une variable utilisateur.

J'essaie d'obtenir un flux d'entrée dans le fichier comme ci-dessous:

Placez le répertoire du fichier (D:\myDir) dans CLASSPATH et essayez ci-dessous:

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

Placez le chemin complet du fichier (D:\myDir\SomeTextFile.txt) dans CLASSPATH et essayez la même chose ci-dessus 3 lignes de code.

Mais malheureusement, AUCUN d’entre eux ne fonctionne et j’enregistre toujours null dans mon InputStream in.

344
Chaitanya MSV

Avec le répertoire sur le chemin de classe, à partir d'une classe chargée par le même chargeur de classes, vous devriez pouvoir utiliser l'un des éléments suivants:

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

Si cela ne fonctionne pas, cela suggère que quelque chose ne va pas.

Ainsi, par exemple, prenons ce 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);
    }
}

Et cette structure de répertoire:

code
    dummy
          Test.class
txt
    SomeTextFile.txt

Et ensuite (en utilisant le séparateur de chemin Unix comme je suis sur une machine Linux):

Java -classpath code:txt dummy.Test

Résultats:

true
true
571
Jon Skeet

Lorsque vous utilisez le cadre Spring (sous forme de collection d'utilitaires ou de conteneur , vous n'avez pas besoin d'utiliser cette dernière fonctionnalité). vous pouvez facilement utiliser l'abstraction Resource.

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

Via l’interface Resource, vous pouvez accéder à la ressource en tant que InputStream, URL, URI ou - Fichier. Changer le type de ressource pour, par exemple, une ressource de système de fichiers consiste simplement à changer l'instance.

114
yawn

Voici comment j'ai lu toutes les lignes d'un fichier texte sur mon chemin de classe, en utilisant 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 ceci est un exemple de la façon dont cela peut être fait. Vous devrez apporter des améliorations si nécessaire. Cet exemple ne fonctionnera que si le fichier est réellement présent sur votre chemin d'accès aux classes. Sinon, une exception NullPointerException sera levée lorsque getResource () renverra null et que .toURI () y sera invoqué.

De plus, depuis Java 7, un moyen pratique de spécifier des jeux de caractères consiste à utiliser les constantes définies dans Java.nio.charset.StandardCharsets (elles sont, selon leur javadocs , "garantis être disponible sur chaque implémentation de la plate-forme Java. ").

Par conséquent, si vous savez que le codage du fichier est UTF-8, spécifiez explicitement le jeu de caractères StandardCharsets.UTF_8

51
Peter Perháč

S'il vous plaît essayez

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

Vos essais n'ont pas fonctionné car seul le chargeur de classes pour votre classes est capable de se charger depuis le classpath. Vous avez utilisé le chargeur de classes pour le système Java lui-même.

25
tangens

Pour lire le contenu du fichier, j'aime bien utiliser Commons IO + Spring Core. En supposant que Java 8:

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

Alternativement:

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

Pour obtenir le chemin absolu de la classe, essayez ceci:

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

D'une certaine manière, la meilleure réponse ne fonctionne pas pour moi. J'ai besoin d'utiliser un code légèrement différent à la place.

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

J'espère que cela aidera ceux qui rencontrent le même problème.

10
user1695166

Si vous utilisez la goyave:

import com.google.common.io.Resources;

nous pouvons obtenir l'URL de CLASSPATH:

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

ou InputStream:

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

Pour lire le contenu d'un fichier dans une chaîne à partir de classpath, vous pouvez utiliser ceci:

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

Remarque:
IOUtils fait partie de Commons IO .

Appelez ça comme ça:

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

Vous dites "J'essaie de lire un fichier texte défini dans la variable système CLASSPATH". Je suppose que c'est sous Windows et que vous utilisez cette boîte de dialogue moche pour éditer les "variables système".

Maintenant, vous exécutez votre programme Java dans la console. Et cela ne fonctionne pas: la console reçoit une copie des valeurs des variables système ne fois quand il s’agit de démarré. Cela signifie que tout changement dans le dialogue après n'a aucun effet.

Il y a ces solutions:

  1. Démarrer une nouvelle console après chaque changement

  2. Utilisez set CLASSPATH=... dans la console pour définir la copie de la variable dans la console. Lorsque votre code fonctionnera, collez la dernière valeur dans le dialogue de variable.

  3. Mettez l'appel à Java dans le fichier .BAT et double-cliquez dessus. Cela créera une nouvelle console à chaque fois (copiant ainsi la valeur actuelle de la variable système).

ATTENTION: Si vous avez également une variable utilisateur CLASSPATH, votre variable système sera alors occultée. C’est pourquoi il est généralement préférable de placer l’appel de votre programme Java dans un fichier .BAT et de définir le chemin d'accès aux classes (avec set CLASSPATH=) plutôt que de s'appuyer sur un système global. ou variable utilisateur.

Cela garantit également que vous pouvez avoir plusieurs programmes Java sur votre ordinateur, car ils doivent obligatoirement avoir différents chemins de classes.

1
Aaron Digulla

Ma réponse n'est pas exactement ce qui est demandé dans la question. Au lieu de cela, je donne une solution exactement avec quelle facilité nous pouvons lire un fichier dans une application Java à partir de notre chemin de classe de projet.

Par exemple, supposons qu'un nom de fichier de configuration example.xml se trouve dans un chemin comme ci-dessous: -

com.myproject.config.dev

et notre fichier de classe exécutable Java se trouve dans le chemin ci-dessous: -

com.myproject.server.main

maintenant, vérifiez simplement dans le chemin ci-dessus qui est le répertoire/dossier commun le plus proche d'où vous pouvez accéder à la fois dev et ) principal répertoire/dossier (com.myproject.server.main - où la classe exécutable Java de notre application est existante) - Nous pouvons voir qu’elle se trouve myproject dossier/répertoire qui est le répertoire/dossier commun le plus proche à partir duquel nous pouvons accéder à notre fichier example.xml. Par conséquent, depuis une classe exécutable Java, elle réside dans le dossier/répertoire principal , nous devons revenir en arrière deux étapes telles que ../../ pour accéder à mon projet . Maintenant, voyez comment on peut lire le fichier: -

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