¿Cómo leer un archivo de texto de classpath en Java?

8 minutos de lectura

Avatar de usuario de Chaitanya MSV
Chaitanya MSV

Estoy tratando de leer un archivo de texto que está configurado en la variable del sistema CLASSPATH. No es una variable de usuario.

Estoy tratando de obtener un flujo de entrada al archivo de la siguiente manera:

Coloque el directorio de archivo (D:\myDir) en CLASSPATH y prueba a continuación:

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

Coloque la ruta completa del archivo (D:\myDir\SomeTextFile.txt) en CLASSPATH e intente lo mismo arriba de 3 líneas de código.

Pero desafortunadamente NINGUNO de ellos está funcionando y siempre recibo null en mi InputStream in.

Avatar de usuario de Jon Skeet
jon skeet

Con el directorio en el classpath, desde una clase cargada por el mismo cargador de clases, debería poder usar cualquiera de los siguientes:

// 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 esos no funcionan, eso sugiere que algo más está mal.

Entonces, por ejemplo, tome este código:

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

Y esta estructura de directorios:

code
    dummy
          Test.class
txt
    SomeTextFile.txt

Y luego (usando el separador de ruta de Unix ya que estoy en una caja de Linux):

java -classpath code:txt dummy.Test

Resultados:

true
true

  • Mezclaste rutas relativas y absolutas hacia arriba. Una ruta que comienza con “/” es absoluta (es decir, comienza desde lo que aparece en CLASSPATH). Todas las demás rutas son relativas al paquete de la clase en la que llama getResourceAsStream()

    – Aarón Digulla

    23 de septiembre de 2009 a las 7:25

  • No tu en bancarrota mi ejemplo Editaré los comentarios para hacerlos más claros, pero el punto es que al usar ClassLoader, se supone que todas las rutas ya son absolutas. No hay nada con lo que ellos sean relativos.

    – Jon Skeet

    23 de septiembre de 2009 a las 7:57

  • Tampoco use Java.IO.File.Separator. No funcionará en Windows. Si está ejecutando este código en Windows, todavía tiene que ser ‘/’ y no ‘\’

    – Pradhan

    14 de junio de 2013 a las 17:56

  • @Pradhan: No, no deberías estar usando File.Separator – porque no estás pidiendo un archivoestás pidiendo un recurso. Es importante entender que la abstracción involucrada no es el sistema de archivos.

    – Jon Skeet

    14 de junio de 2013 a las 17:59

  • @jagdpanzer: Bueno, es solo para clases que son cargadas por el mismo cargador de clases, básicamente, y es porque Class.getResourceAsStream es realmente un método conveniente para llamar ClassLoader.getResourceAsStream, pero con la característica adicional de recursos “relativos”. Si está especificando un recurso absoluto, entonces cualquier llamada que use el mismo cargador de clases hará lo mismo.

    – Jon Skeet

    5 de noviembre de 2015 a las 18:07

Al usar el Primavera Framework (ya sea como una colección de utilidades o contenedor – no necesita usar la última funcionalidad) puede usar fácilmente el Recurso abstracción.

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

A través de Recurso interfaz puede acceder al recurso como Flujo de entrada, URL, URI o Archivo. Cambiar el tipo de recurso a, por ejemplo, un recurso del sistema de archivos es una simple cuestión de cambiar la instancia.

  • ¿Podría proporcionar un código de muestra sobre cómo se puede usar esto en la E/S de archivos? no puedo encontrar un decente, explícito y directo forma de usarlo en Internet :((((

    usuario1685185

    11/02/2014 a las 16:00

  • Funciona de maravilla. El forro provisto es todo lo que necesita. Utilice el análisis de flujo de otros ejemplos si no sabe cómo obtener una cadena del flujo.

    – José Lujuria

    16 de febrero de 2014 a las 18:14

  • También tuve algunos problemas para averiguar exactamente qué hacer con la variable de recursos. He editado la respuesta con un poco más de detalle.

    – DavidZemon

    2 de diciembre de 2014 a las 14:10

  • Ya estaba usando Spring y probando la forma de “java puro”. Me estaba matando, las diferencias entre getResource, getResourceAsStream, etc., sin buenos ejemplos de trabajo. Este es un ejemplo perfecto de encapsulación, así que no tiene que importarme.

    – TinkerTenorSoftwareGuy

    19 de enero de 2017 a las 16:08

  • Tenga cuidado, si empaqueta su proyecto en un contenedor, debe usar un InputStream. Si usa un archivo, funcionará en su IDE pero fallará si lo prueba desde el contenedor. Si realmente necesita un archivo, intente con stackoverflow.com/questions/4317035/…

    –Rafael Membrives

    30 de agosto de 2017 a las 7:40

Avatar de usuario de Peter Perháč
Peter Perhač

Así es como leo todas las líneas de un archivo de texto en mi classpath, usando 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, este es un ejemplo de cómo se puede hacer. Tendrás que hacer mejoras según sea necesario. Este ejemplo solo funcionará si el archivo está realmente presente en su classpath; de lo contrario, se lanzará una NullPointerException cuando getResource() devuelva nulo y se invoque .toURI() en él.

Además, desde Java 7, una forma conveniente de especificar juegos de caracteres es usar las constantes definidas en java.nio.charset.StandardCharsets
(estos son, según su javadocs“garantizado de estar disponible en todas las implementaciones de la plataforma Java”).

Por lo tanto, si sabe que la codificación del archivo es UTF-8, especifique explícitamente el conjunto de caracteres StandardCharsets.UTF_8

  • Gracias por la solución NIO: tan poca gente usa esta gran API, es una pena.

    – mvreijn

    14/04/2015 a las 18:50

  • Para leer en una sola cadena, intente. new String(Files.readAllBytes(Paths.get(MyClass.class.getResource(resource).toURI())));

    – Theo Briscoe

    23 de julio de 2016 a las 12:03

  • La mejor solución para mí, ya que no necesita dependencias, como Spring o Commons IO.

    – Bernie

    25 de septiembre de 2016 a las 9:44

  • Esto fallará si su archivo de recursos está dentro de un contenedor, por ejemplo, un módulo maven. En ese caso necesitarás usar algo como Spring‘s StreamUtils.copyToString.

    – Somu

    14 de febrero de 2020 a las 9:33

Por favor, inténtalo

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

Tus intentos no funcionaron porque solo el cargador de clases para su Las clases pueden cargarse desde el classpath. Usaste el cargador de clases para el propio sistema java.

Avatar de usuario de Pavel
pavel

Para leer realmente el contenido del archivo, me gusta usar Commons IO + Spring Core. Asumiendo Java 8:

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

Alternativamente:

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

  • ¿Qué hay de cerrar el flujo de entrada?

    – Stephan

    21 de abril de 2016 a las 15:32

  • La transmisión se cerrará automáticamente. Es una característica de Java 7 “Probar con recursos” docs.oracle.com/javase/tutorial/essential/exceptions/…

    – Michał Maciej Gałuszka

    13 de septiembre de 2018 a las 6:58

  • Solo si está dentro de la sentencia try, que no es el caso aquí. Debería haberlo intentado (secuencia final de InputStream = new ClassPathResource(“/log4j.xml”).getInputStream()) {…

    – andresp

    13 de mayo de 2019 a las 13:23

Avatar de usuario de 5agado
5agado

Para obtener la ruta absoluta de la clase, intente esto:

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

  • ¿Qué hay de cerrar el flujo de entrada?

    – Stephan

    21 de abril de 2016 a las 15:32

  • La transmisión se cerrará automáticamente. Es una característica de Java 7 “Probar con recursos” docs.oracle.com/javase/tutorial/essential/exceptions/…

    – Michał Maciej Gałuszka

    13 de septiembre de 2018 a las 6:58

  • Solo si está dentro de la sentencia try, que no es el caso aquí. Debería haberlo intentado (secuencia final de InputStream = new ClassPathResource(“/log4j.xml”).getInputStream()) {…

    – andresp

    13 de mayo de 2019 a las 13:23

avatar de usuario de user1695166
usuario1695166

De alguna manera, la mejor respuesta no funciona para mí. Necesito usar un código ligeramente diferente en su lugar.

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

Espero que esto ayude a aquellos que se encuentran con el mismo problema.

  • Esto también me ayudó en Android, donde el cargador de aplicaciones cargó una clase, pero una clave que necesitaba se cargó de forma diferida en el subproceso de la interfaz de usuario.

    – asoka

    04/07/2016 a las 22:35

  • Debe proporcionar información sobre por qué la mejor respuesta no funciona para usted (por ejemplo, la estructura de su aplicación, el marco que está utilizando, el error, etc.). La mejor respuesta decía claramente que 1) el directorio debe estar en classpath, 2) debe solicitar una clase cargada por el mismo cargador de clases. Lo más probable es que una de estas suposiciones no se cumpla para su aplicación. Además, el cargador de clases de contexto está muy desaconsejado, ya que se introdujo como un truco. Algunos marcos lo utilizan, pero es importante conocer la implicación (que requiere que describa los antecedentes de su proyecto)

    – Xinchao

    20 de julio de 2018 a las 6:43

  • Esto funciona en un contexto estático (a diferencia de otras soluciones mencionadas aquí).

    – Vitali Sazanovich

    21 de junio de 2021 a las 20:17

¿Ha sido útil esta solución?