web-dev-qa-db-fra.com

Comment lire un fichier depuis un fichier jar?

J'ai un fichier dans un fichier JAR. C'est 1.txt, par exemple.

Comment puis-je y accéder? Mon code source est:

Double result=0.0;
File file = new File("1.txt")); //how get this file from a jar file
BufferedReader input = new BufferedReader(new FileReader(file));
String line;
while ((line = input.readLine()) != null) {
  if(me==Integer.parseInt(line.split(":")[0])){
    result= parseDouble(line.split(":")[1]);
  }
}
input.close();
return result;
29
Freeman

Vous ne pouvez pas utiliser Fichier, car ce fichier n'existe pas indépendamment sur le système de fichiers. Au lieu de cela, vous avez besoin de getResourceAsStream (), comme ceci:

...
InputStream in = getClass().getResourceAsStream("/1.txt");
BufferedReader input = new BufferedReader(new InputStreamReader(in));
...
29
Sean Owen

Si votre pot est sur le chemin de la classe:

InputStream is = YourClass.class.getResourceAsStream("1.txt");

S'il n'est pas sur le chemin de classe, vous pouvez y accéder via:

URL url = new URL("jar:file:/absolute/location/of/yourJar.jar!/1.txt");
InputStream is = url.openStream();
47
Bozho

Quelque chose de similaire à cette réponse est ce dont vous avez besoin.

Vous devez extraire le fichier de l'archive de cette manière spéciale.

BufferedReader input = new BufferedReader(new InputStreamReader(
         this.getClass().getClassLoader().getResourceAsStream("1.txt")));
4
jjnguy

Un fichier Jar est un fichier Zip .....

Donc, pour lire un fichier jar, essayez

ZipFile file = new ZipFile("whatever.jar");
if (file != null) {
   ZipEntries entries = file.entries(); //get entries from the Zip file...

   if (entries != null) {
      while (entries.hasMoreElements()) {
          ZipEntry entry = entries.nextElement();

          //use the entry to see if it's the file '1.txt'
          //Read from the byte using file.getInputStream(entry)
      }
    }
}

J'espère que cela t'aides.

4
Buhake Sindi
private String loadResourceFileIntoString(String path) {
    //path = "/resources/html/custom.css" for example
    BufferedReader buffer = new BufferedReader(new InputStreamReader(getClass().getResourceAsStream(path)));
    return buffer.lines().collect(Collectors.joining(System.getProperty("line.separator")));
}
2
jk1971

J'ai rencontré ce même problème plusieurs fois auparavant. J'espérais dans JDK 7 que quelqu'un écrirait un système de fichiers classpath, mais hélas pas encore.

Spring a la classe Resource qui vous permet de charger assez bien les ressources classpath.

Les réponses ont été très bonnes, mais j'ai pensé pouvoir ajouter à la discussion en montrant un exemple qui fonctionne avec des fichiers et des répertoires qui sont des ressources de chemin de classe.

J'ai écrit un petit prototype pour résoudre ce problème. Le prototype ne gère pas tous les cas Edge, mais il gère la recherche de ressources dans les répertoires qui se trouvent dans les fichiers jar.

J'utilise Stack Overflow depuis un certain temps. C'est la première fois que je me souviens avoir répondu à une question alors pardonnez-moi si je vais trop longtemps (c'est ma nature).



    package com.foo;

    import Java.io.File;
    import Java.io.FileReader;
    import Java.io.InputStreamReader;
    import Java.io.Reader;
    import Java.net.URI;
    import Java.net.URL;
    import Java.util.Enumeration;
    import Java.util.Zip.ZipEntry;
    import Java.util.Zip.ZipFile;

    /**
    * Prototype resource reader.
    * This prototype is devoid of error checking.
    *
    *
    * I have two prototype jar files that I have setup.
    * <pre>
    *             <dependency>
    *                  <groupId>invoke</groupId>
    *                  <artifactId>invoke</artifactId>
    *                  <version>1.0-SNAPSHOT</version>
    *              </dependency>
    *
    *              <dependency>
    *                   <groupId>node</groupId>
    *                   <artifactId>node</artifactId>
    *                   <version>1.0-SNAPSHOT</version>
    *              </dependency>
    * </pre>
    * The jar files each have a file under /org/node/ called resource.txt.
    * <br />
    * This is just a prototype of what a handler would look like with classpath://
    * I also have a resource.foo.txt in my local resources for this project.
    * <br />
    */
    public class ClasspathReader {

        public static void main(String[] args) throws Exception {

            /* This project includes two jar files that each have a resource located
               in /org/node/ called resource.txt.
             */


            /* 
              Name space is just a device I am using to see if a file in a dir
              starts with a name space. Think of namespace like a file extension 
              but it is the start of the file not the end.
            */
            String namespace = "resource";

            //someResource is classpath.
            String someResource = args.length > 0 ? args[0] :
                    //"classpath:///org/node/resource.txt";   It works with files
                    "classpath:///org/node/";                 //It also works with directories

            URI someResourceURI = URI.create(someResource);

            System.out.println("URI of resource = " + someResourceURI);

            someResource = someResourceURI.getPath();

            System.out.println("PATH of resource =" + someResource);

            boolean isDir = !someResource.endsWith(".txt");


            /** Classpath resource can never really start with a starting slash.
             * Logically they do, but in reality you have to strip it.
             * This is a known behavior of classpath resources.
             * It works with a slash unless the resource is in a jar file.
             * Bottom line, by stripping it, it always works.
             */
            if (someResource.startsWith("/")) {
                someResource = someResource.substring(1);
            }

              /* Use the ClassLoader to lookup all resources that have this name.
                 Look for all resources that match the location we are looking for. */
            Enumeration resources = null;

            /* Check the context classloader first. Always use this if available. */
            try {
                resources = 
                    Thread.currentThread().getContextClassLoader().getResources(someResource);
            } catch (Exception ex) {
                ex.printStackTrace();
            }

            if (resources == null || !resources.hasMoreElements()) {
                resources = ClasspathReader.class.getClassLoader().getResources(someResource);
            }

            //Now iterate over the URLs of the resources from the classpath
            while (resources.hasMoreElements()) {
                URL resource = resources.nextElement();


                /* if the resource is a file, it just means that we can use normal mechanism
                    to scan the directory.
                */
                if (resource.getProtocol().equals("file")) {
                    //if it is a file then we can handle it the normal way.
                    handleFile(resource, namespace);
                    continue;
                }

                System.out.println("Resource " + resource);

               /*

                 Split up the string that looks like this:
                 jar:file:/Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar!/org/node/
                 into
                    this /Users/rick/.m2/repository/invoke/invoke/1.0-SNAPSHOT/invoke-1.0-SNAPSHOT.jar
                 and this
                     /org/node/
                */
                String[] split = resource.toString().split(":");
                String[] split2 = split[2].split("!");
                String zipFileName = split2[0];
                String sresource = split2[1];

                System.out.printf("After split Zip file name = %s," +
                        " \nresource in Zip %s \n", zipFileName, sresource);


                /* Open up the Zip file. */
                ZipFile zipFile = new ZipFile(zipFileName);


                /*  Iterate through the entries.  */
                Enumeration entries = zipFile.entries();

                while (entries.hasMoreElements()) {
                    ZipEntry entry = entries.nextElement();
                    /* If it is a directory, then skip it. */
                    if (entry.isDirectory()) {
                        continue;
                    }

                    String entryName = entry.getName();
                    System.out.printf("Zip entry name %s \n", entryName);

                    /* If it does not start with our someResource String
                       then it is not our resource so continue.
                    */
                    if (!entryName.startsWith(someResource)) {
                        continue;
                    }


                    /* the fileName part from the entry name.
                     * where /foo/bar/foo/bee/bar.txt, bar.txt is the file
                     */
                    String fileName = entryName.substring(entryName.lastIndexOf("/") + 1);
                    System.out.printf("fileName %s \n", fileName);

                    /* See if the file starts with our namespace and ends with our extension.        
                     */
                    if (fileName.startsWith(namespace) && fileName.endsWith(".txt")) {


                        /* If you found the file, print out 
                           the contents fo the file to System.out.*/
                        try (Reader reader = new InputStreamReader(zipFile.getInputStream(entry))) {
                            StringBuilder builder = new StringBuilder();
                            int ch = 0;
                            while ((ch = reader.read()) != -1) {
                                builder.append((char) ch);

                            }
                            System.out.printf("Zip fileName = %s\n\n####\n contents of file %s\n###\n", entryName, builder);
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }
                    }

                    //use the entry to see if it's the file '1.txt'
                    //Read from the byte using file.getInputStream(entry)
                }

            }


        }

        /**
         * The file was on the file system not a Zip file,
         * this is here for completeness for this example.
         * otherwise.
         *
         * @param resource
         * @param namespace
         * @throws Exception
         */
        private static void handleFile(URL resource, String namespace) throws Exception {
            System.out.println("Handle this resource as a file " + resource);
            URI uri = resource.toURI();
            File file = new File(uri.getPath());


            if (file.isDirectory()) {
                for (File childFile : file.listFiles()) {
                    if (childFile.isDirectory()) {
                        continue;
                    }
                    String fileName = childFile.getName();
                    if (fileName.startsWith(namespace) && fileName.endsWith("txt")) {

                        try (FileReader reader = new FileReader(childFile)) {
                            StringBuilder builder = new StringBuilder();
                            int ch = 0;
                            while ((ch = reader.read()) != -1) {
                                builder.append((char) ch);

                            }
                            System.out.printf("fileName = %s\n\n####\n contents of file %s\n###\n", childFile, builder);
                        } catch (Exception ex) {
                            ex.printStackTrace();
                        }

                    }

                }
            } else {
                String fileName = file.getName();
                if (fileName.startsWith(namespace) && fileName.endsWith("txt")) {

                    try (FileReader reader = new FileReader(file)) {
                        StringBuilder builder = new StringBuilder();
                        int ch = 0;
                        while ((ch = reader.read()) != -1) {
                            builder.append((char) ch);

                        }
                        System.out.printf("fileName = %s\n\n####\n contents of file %s\n###\n", fileName, builder);
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }

                }

            }
        }

    }


   

Vous pouvez voir un exemple plus complet ici avec l'exemple de sortie.

1
RickHigh

Cela a fonctionné pour moi de copier un fichier txt du fichier jar vers un autre fichier txt

public static void copyTextMethod() throws Exception{
    String inputPath = "path/to/.jar";
    String outputPath = "Desktop/CopyText.txt";

    File resStreamOut = new File(outputPath);

     int readBytes;
     JarFile file = new JarFile(inputPath);

     FileWriter fw = new FileWriter(resStreamOut);

    try{
        Enumeration<JarEntry> entries = file.entries();
        while (entries.hasMoreElements()){
            JarEntry entry = entries.nextElement();
        if (entry.getName().equals("readMe/tempReadme.txt")) {

                System.out.println(entry +" : Entry");
            InputStream is = file.getInputStream(entry);
            BufferedWriter output = new BufferedWriter(fw);
                 while ((readBytes = is.read()) != -1) {
                    output.write((char) readBytes);
                 }
                System.out.println(outputPath);
                output.close();
            } 
        }
    } catch(Exception er){
        er.printStackTrace();
    }
        }
            }
1