2010-02-16 2 views
28

У меня есть файл в JAR-файле. Например, это 1.txt.Как читать файл из файла jar?

Как я могу получить к нему доступ? Мой исходный код:

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; 
+0

см http://stackoverflow.com/questions/16842306 – yegor256

+0

Возможный дубликат [Как прочитать файл ресурсов из файла jar jar?] (Http://stackoverflow.com/questions/403256/how-do-i-read-a-res ource-file-from-a-java-jar-file) – davecom

+0

Возможный дубликат [Как прочитать файл из jar в Java?] (http://stackoverflow.com/questions/3369794/how-to-a-read -file-from-jar-in-java) – Qix

ответ

27

Вы не можете использовать File, так как этот файл не существует независимо в файловой системе. Вместо этого вам нужно getResourceAsStream(), например так:

... 
InputStream in = getClass().getResourceAsStream("/1.txt"); 
BufferedReader input = new BufferedReader(new InputStreamReader(in)); 
... 
+2

Предполагая, что вызывающий класс находится внутри файла jar.В противном случае он может просто разархивировать его, прочитав его, используя классы в java.util.jar (или даже более простые, как обычный старый zip-файл с помощью 'java.util.zip'). –

4

Нечто подобное this answer то, что вам нужно.

Вам необходимо вытащить файл из архива специальным образом.

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

BufferedReader не использует аргумент 'InputStream' – Bozho

+0

@Bozho Спасибо, небольшой контроль с моей стороны. – jjnguy

+0

Я слишком застрял в этом, благодаря вашей методической работе. –

46

Если баночка находится на пути к классам:

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

Если это не на пути к классам, то вы можете получить доступ к нему через:

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

Также не забудьте включить этот восклицательный знак после банки. Это необязательно. – hsmishka

+0

Есть ли способ проверить это? (используя jUnit, testNG, Spock, ...). Я попробовал, но файлы не были найдены во время тестов. – Edward

+0

Спасибо за ваш ответ. Эта часть "url.openStream();" это то, что мне нужно. – jmgoyesc

4

файл Jar на молнии файл .....

Чтобы прочитать файл в баночке, попробуйте

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

Надеюсь, это поможет.

+0

Другие ответы верны, я просто дал еще одну альтернативу. –

0

Я уже несколько раз сталкивался с этой проблемой. Я надеялся в JDK 7, что кто-то напишет файловую систему classpath, но, увы, еще нет.

Весна имеет класс ресурсов, который позволяет вам легко загружать ресурсы класса.

Ответы были очень хорошими, но я подумал, что могу добавить к обсуждению пример, который работает с файлами и каталогами, которые являются ресурсами класса.

Я написал небольшой прототип, чтобы решить эту проблему. Прототип не обрабатывает каждый край, но он обрабатывает поиск ресурсов в каталогах, которые находятся в файлах jar.

Я использовал переполнение стека в течение некоторого времени. Это первый случай, когда я вспоминаю ответ на вопрос, поэтому простите меня, если я буду долго (это моя природа).

 
    

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

       } 

      } 
     } 

    } 


 

You can see a fuller example here with the sample output.

1

Это работает для меня, чтобы скопировать текстовый файл из JAR-файла в другой текстовый файл

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
InputStream inputStreamLastName = this.getClass().getClassLoader().getResourceAsStream("path of file"); 


    try { 

     br = new BufferedReader(new InputStreamReader(inputStreamLastName, "UTF-8")); 
     String sCurrentLine; 
     ArrayList<String> lastNamesList = new ArrayList<String>(); 
     while ((sCurrentLine = br.readLine()) != null) { 

      if(sCurrentLine.length()>=min && sCurrentLine.length()<=max){ 
       lastNamesList.add(sCurrentLine); 
      } 

     } 
+0

Добавьте некоторое объяснение с ответом на вопрос, как этот ответ помогает OP в устранении текущей проблемы –

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

 Смежные вопросы

  • Нет связанных вопросов^_^