¿Cómo cargo un archivo de la carpeta de recursos?

240

Mi proyecto tiene la siguiente estructura:

/src/main/java/
/src/main/resources/
/src/test/java/
/src/test/resources/

Tengo un archivo /src/test/resources/test.csvy quiero cargar el archivo desde una prueba unitaria en/src/test/java/MyTest.java

Tengo este código que no funcionó. Se queja "No existe tal archivo o directorio".

BufferedReader br = new BufferedReader (new FileReader(test.csv))

También probé esto

InputStream is = (InputStream) MyTest.class.getResourcesAsStream(test.csv))

Esto tampoco funciona. Vuelve null. Estoy usando Maven para construir mi proyecto.

codereviewanskquestions
fuente
¿No funciona cómo? Cual es tu error?
Daniel Kaplan
17
intente estothis.getClass().getResource("/test.csv")
SRy
@SRy funcionó (porque esto le dará url ruta absoluta a cambio) sin embargo, el momento en que hago archivo jar no funciona como dentro de un frasco y la ruta absoluta se vuelve inválida, ¿hay una manera de jugar con la misma ruta relativa
ShankPossible

Respuestas:

240

Intenta lo siguiente:

ClassLoader classloader = Thread.currentThread().getContextClassLoader();
InputStream is = classloader.getResourceAsStream("test.csv");

Si lo anterior no funciona, se han agregado varios proyectos a la siguiente clase: 1 (código aquí ). 2ClassLoaderUtil

Aquí hay algunos ejemplos de cómo se usa esa clase:

src \ main \ java \ com \ company \ test \ YourCallingClass.java
src \ main \ java \ com \ opensymphony \ xwork2 \ util \ ClassLoaderUtil.java
src \ main \ resources \ test.csv
// java.net.URL
URL url = ClassLoaderUtil.getResource("test.csv", YourCallingClass.class);
Path path = Paths.get(url.toURI());
List<String> lines = Files.readAllLines(path, StandardCharsets.UTF_8);
// java.io.InputStream
InputStream inputStream = ClassLoaderUtil.getResourceAsStream("test.csv", YourCallingClass.class);
InputStreamReader streamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
BufferedReader reader = new BufferedReader(streamReader);
for (String line; (line = reader.readLine()) != null;) {
    // Process line
}

Notas

  1. Véalo en The Wayback Machine .
  2. También en GitHub .
Paul Vargas
fuente
14
Gracias por la respuesta, ¿podría explicar por qué deberíamos usar este cargador muy específico pero no el de la clase?
Hui Wang
1
genial, soy tan estúpido que estaba usando Object.class.getClassLoader();, desde un contexto estático que no funcionó, esta sugerencia sí funciona, bueno, casi inyecta %20espacios, lo que me da unFileNotFoundException
ycomp
55
@ycomp Porque getResource devuelve una URL, no un archivo. El método getFile de java.net.URL no convierte una URL en un archivo; solo devuelve la ruta y las partes de consulta de la URL. Ni siquiera deberías intentar convertirlo en un archivo; simplemente llame a openStream y lea de eso.
VGR
Consulte este proyecto, resuelve el escaneo de carpetas de recursos: github.com/fraballi/resources-folder-scanner
Felix Aballi
60

Tratar:

InputStream is = MyTest.class.getResourceAsStream("/test.csv");

IIRC getResourceAsStream()por defecto es relativo al paquete de la clase.

Como señaló @Terran, no olvide agregar el /al comienzo del nombre de archivo

vanza
fuente
3
Para aquellos que buscan cordura, esta publicación les ofrece todo el camino para obtener el recurso como String stackoverflow.com/a/35446009/544045
Trevor
12
El "/" es la clave.
Terran
33

Aquí hay una solución rápida con el uso de guayaba :

import com.google.common.base.Charsets;
import com.google.common.io.Resources;

public String readResource(final String fileName, Charset charset) throws IOException {
        return Resources.toString(Resources.getResource(fileName), charset);
}

Uso:

String fixture = this.readResource("filename.txt", Charsets.UTF_8)
Datageek
fuente
28

Pruebe los códigos de flujo en el proyecto Spring

ClassPathResource resource = new ClassPathResource("fileName");
InputStream inputStream = resource.getInputStream();

O en un proyecto que no sea de primavera

 ClassLoader classLoader = getClass().getClassLoader();
 File file = new File(classLoader.getResource("fileName").getFile());
 InputStream inputStream = new FileInputStream(file);
srsajid
fuente
¿No se debe cerrar InputStream?
030
7

Proyecto no primaveral:

String filePath = Objects.requireNonNull(MyClass.class.getClassLoader().getResource("any.json")).getPath();

Stream<String> lines = Files.lines(Paths.get(filePath));

Para proyectos de primavera, también puede usar un código de línea para obtener cualquier archivo en la carpeta de recursos:

File file = ResourceUtils.getFile(ResourceUtils.CLASSPATH_URL_PREFIX + "any.json");

String content = new String(Files.readAllBytes(file.toPath()));
fuat
fuente
5

Ahora estoy ilustrando el código fuente para leer una fuente del directorio de recursos creados por Maven,

scr / main / resources / calibril.ttf

ingrese la descripción de la imagen aquí

Font getCalibriLightFont(int fontSize){
    Font font = null;
    try{
        URL fontURL = OneMethod.class.getResource("/calibril.ttf");
        InputStream fontStream = fontURL.openStream();
        font = new Font(Font.createFont(Font.TRUETYPE_FONT, fontStream).getFamily(), Font.PLAIN, fontSize);
        fontStream.close();
    }catch(IOException | FontFormatException ief){
        font = new Font("Arial", Font.PLAIN, fontSize);
        ief.printStackTrace();
    }   
    return font;
}

Funcionó para mí y espero que todo el código fuente también te ayude, ¡Disfruta!

ArifMustafa
fuente
5

Para java después de 1.7

 List<String> lines = Files.readAllLines(Paths.get(getClass().getResource("test.csv").toURI()));
phray2002
fuente
Debo usar "/test.csv" (tenga en cuenta la barra).
Leon
4
ClassLoader loader = Thread.currentThread().getContextClassLoader();
InputStream is = loader.getResourceAsStream("test.csv");

Si utiliza el ClassLoader de contexto para encontrar un recurso, definitivamente le costará el rendimiento de la aplicación.

Bimales Mandal
fuente
44
Los programadores siempre deben preocuparse por el rendimiento. Si bien se debe evitar la optimización prematura, siempre es bueno conocer el enfoque más eficiente. Es como saber la diferencia entre LinkedList y ArrayList y cuándo usar uno u otro.
Marvo
66
@Marvo: Los programadores siempre deben preocuparse por la calidad, las capacidades y la facilidad de mantenimiento, el rendimiento está en la cola.
Igor Rodriguez
2

Importa lo siguiente:

import java.io.IOException;
import java.io.FileNotFoundException;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.io.InputStream;
import java.util.ArrayList;

El siguiente método devuelve un archivo en una ArrayList of Strings:

public ArrayList<String> loadFile(String filename){

  ArrayList<String> lines = new ArrayList<String>();

  try{

    ClassLoader classloader = Thread.currentThread().getContextClassLoader();
    InputStream inputStream = classloader.getResourceAsStream(filename);
    InputStreamReader streamReader = new InputStreamReader(inputStream, StandardCharsets.UTF_8);
    BufferedReader reader = new BufferedReader(streamReader);
    for (String line; (line = reader.readLine()) != null;) {
      lines.add(line);
    }

  }catch(FileNotFoundException fnfe){
    // process errors
  }catch(IOException ioe){
    // process errors
  }
  return lines;
}
shalamus
fuente
2

Me enfrenté al mismo problema .

El cargador de clases no encontró el archivo, lo que significa que no estaba empaquetado en el artefacto (jar). Necesitas construir el proyecto . Por ejemplo, con maven:

mvn clean install

Por lo tanto, los archivos que agregó a la carpeta de recursos entrarán en la compilación de Maven y estarán disponibles para la aplicación.

Me gustaría conservar mi respuesta: no explica cómo leer un archivo (otras respuestas sí lo explican), responde por qué InputStream o resourcefue nulo . Una respuesta similar está aquí .

Yan Khonski
fuente
1
¡Gracias, me salvó de pensar que me estaba volviendo loco!
StuPointerException
1

getResource () funcionaba bien con los archivos de recursos colocados src/main/resourcessolo. Para obtener un archivo que se encuentra en la ruta de acceso, aparte de src/main/resourcesdecir src/test/java, debe crearlo de forma explícita.

el siguiente ejemplo puede ayudarte

import java.io.BufferedReader;
import java.io.FileReader;
import java.io.IOException;
import java.net.URISyntaxException;
import java.net.URL;

public class Main {
    public static void main(String[] args) throws URISyntaxException, IOException {
        URL location = Main.class.getProtectionDomain().getCodeSource().getLocation();
        BufferedReader br = new BufferedReader(new FileReader(location.getPath().toString().replace("/target/classes/", "/src/test/java/youfilename.txt")));
    }
}
Piyush Mittal
fuente
0

¿Funciona el código cuando no se ejecuta el jar Maven-build, por ejemplo, cuando se ejecuta desde su IDE? Si es así, asegúrese de que el archivo esté realmente incluido en el jar. La carpeta de recursos debe incluirse en el archivo pom, en <build><resources>.

Jorn
fuente
Al usar eclipse y ejecutar código desde IDE. ¿Cómo podemos cargar recursos ubicados en "/ src / test / resources" en código Java específicamente en pruebas unitarias? Considere una estructura estándar de proyecto maven.
Bhavesh
0

La siguiente clase se puede usar para cargar un resourcedesde classpathy también recibir un mensaje de error de ajuste en caso de que haya un problema con el dado filePath.

import java.io.InputStream;
import java.nio.file.NoSuchFileException;

public class ResourceLoader
{
    private String filePath;

    public ResourceLoader(String filePath)
    {
        this.filePath = filePath;

        if(filePath.startsWith("/"))
        {
            throw new IllegalArgumentException("Relative paths may not have a leading slash!");
        }
    }

    public InputStream getResource() throws NoSuchFileException
    {
        ClassLoader classLoader = this.getClass().getClassLoader();

        InputStream inputStream = classLoader.getResourceAsStream(filePath);

        if(inputStream == null)
        {
            throw new NoSuchFileException("Resource file not found. Note that the current directory is the source folder!");
        }

        return inputStream;
    }
}
BullyWiiPlaza
fuente
0

Resolví este problema agregando /scr/main/resourcescarpeta a miJava Build Path

ingrese la descripción de la imagen aquí

sklimkovitch
fuente
intente esto, pero esta no es la solución
Jasonw
0

Lo hice funcionar tanto en jar jar como en IDE escribiendo como

 InputStream schemaStream = ProductUtil.class.getClassLoader().getResourceAsStream(jsonSchemaPath);
            byte[] buffer = new byte[schemaStream.available()];
            schemaStream.read(buffer);

        File tempFile = File.createTempFile("com/package/schema/testSchema", "json");
        tempFile.deleteOnExit();
        FileOutputStream out = new FileOutputStream(tempFile);
        out.write(buffer);
rakeeee
fuente
¿Cómo se ve la estructura de tu archivo?
luckydonald
0
this.getClass().getClassLoader().getResource("filename").getPath()
shiva kumar
fuente
0

Puede usar com.google.common.io.Resources.getResource para leer la url del archivo y luego obtener el contenido del archivo usando java.nio.file.Files para leer el contenido del archivo.

URL urlPath = Resources.getResource("src/main/resource");
List<String> multilineContent= Files.readAllLines(Paths.get(urlPath.toURI()));
Bhawna Joshi
fuente
-2

Lo hago funcionar sin ninguna referencia a "clase" o "ClassLoader".

Digamos que tenemos tres escenarios con la ubicación del archivo 'example.file' y su directorio de trabajo (donde se ejecuta su aplicación) es home / mydocuments / program / projects / myapp:

a) Una subcarpeta que desciende al directorio de trabajo: myapp / res / files / example.file

b) Una subcarpeta que no desciende al directorio de trabajo: projects / files / example.file

b2) Otra subcarpeta que no desciende al directorio de trabajo: program / files / example.file

c) Una carpeta raíz: home / mydocuments / files / example.file (Linux; en Windows reemplace home / con C :)

1) Obtenga el camino correcto: a) String path = "res/files/example.file"; b) String path = "../projects/files/example.file" b2) String path = "../../program/files/example.file" c)String path = "/home/mydocuments/files/example.file"

Básicamente, si se trata de una carpeta raíz, inicie el nombre de la ruta con una barra diagonal. Si es una subcarpeta, no debe haber una barra inclinada antes del nombre de la ruta. Si la subcarpeta no desciende al directorio de trabajo, debe cd a ella usando "../". Esto le dice al sistema que suba una carpeta.

2) Cree un objeto File pasando la ruta correcta:

File file = new File(path);

3) Ahora estás listo para ir:

BufferedReader br = new BufferedReader(new FileReader(file));
AndreGraveler
fuente