web-dev-qa-db-fra.com

Lire le fichier de classpath avec Java 7 NIO

Cela fait un moment que je cherche dans Google, mais tous les résultats vont dans le sens des solutions NIO antérieures à Java 7. J'ai utilisé le fichier NIO pour lire des fichiers à partir d'un emplacement spécifique du système de fichiers, et c'était tellement plus simple qu'auparavant (Files.readAllBytes(path)). Maintenant, je veux lire dans un fichier qui est emballé dans mon fichier WAR et sur le classpath. Nous le faisons actuellement avec un code similaire à celui-ci:

Input inputStream = this.getClass().getClassLoader().getResourceAsStream(fileName);
ByteArrayOutputStream byteStream = new ByteArrayOutputStream();

/* iterate through the input stream to get all the bytes (no way to reliably find the size of the 
 *     file behind the inputStream (see http://docs.Oracle.com/javase/6/docs/api/Java/io/InputStream.html#available()))
 */
int byteInt = -1;
try
{
    byteInt = inputStream.read();
    while (byteInt != -1)
    {
        byteStream.write(byteInt);
        byteInt = inputStream.read();
    }

    byteArray = byteStream.toByteArray();
    inputStream.close();
    return byteArray;
}
catch (IOException e)
{
    //...
}

Pendant que cela fonctionnait, j'espérais qu'il existait un moyen plus simple/meilleur de le faire avec les éléments NIO dans Java 7. J'imagine qu'il me faudra un objet Path qui représente ce chemin sur le chemin d'accès aux classes, mais je ne sais pas comment faire ça.

Je m'excuse si c'est une chose super facile à faire. Je n'arrive pas à comprendre. Merci pour l'aide.

13
dnc253

Un chemin représente un fichier sur le système de fichiers. Cela n'aide pas de lire une ressource du classpath. Ce que vous cherchez, c'est une méthode d'assistance qui lit tout d'un flux (plus efficacement que vous le faites) et l'écrit dans un tableau d'octets. Apache commons-io ou Guava peut vous aider. Par exemple avec la goyave:

byte[] array = 
    ByteStreams.toByteArray(this.getClass().getClassLoader().getResourceAsStream(resourceName));

Si vous ne voulez pas ajouter Guava ou commons-io à vos dépendances rien que pour ça, vous pouvez toujours lire leur code source et le dupliquer dans votre propre méthode d'assistance.

7
JB Nizet

Cela fonctionne pour moi.

import Java.nio.file.Files;
import Java.nio.file.Paths;

// fileName: foo.txt which lives under src/main/resources
public String readFileFromClasspath(final String fileName) throws IOException, URISyntaxException {
    return new String(Files.readAllBytes(
                Paths.get(getClass().getClassLoader()
                        .getResource(fileName)
                        .toURI())));
}
26
shreyas

Autant que je sache, vous souhaitez ouvrir une ReadableByteChannel dans votre ressource afin de pouvoir utiliser NIO pour la lire.

Cela devrait être un bon début,

// Opens a resource from the current class' defining class loader
InputStream istream = getClass().getResourceAsStream("/filename.txt");

// Create a NIO ReadableByteChannel from the stream
ReadableByteChannel channel = Java.nio.channels.Channels.newChannel(istream);
2
Joachim Isaksson

Vous devriez regarder ClassLoader.getResource(). Ceci retourne une URL qui représente la ressource. Si elle est locale au système de fichiers, il s'agira d'une URL file://. À ce stade, vous pouvez supprimer le schéma, etc., puis vous avez le nom du fichier avec lequel vous pouvez faire ce que vous voulez.

Cependant, si ce n'est pas un chemin file: //, vous pouvez alors revenir au InputStream normal.

1
Will Hartung