2013-12-05 2 views
114

Я хотел бы прочитать ресурс из моей фляги так:Чтение файла ресурсов внутри баночки

File file; 
file = new File(getClass().getResource("/file.txt").toURI()); 
BufferredReader reader = new BufferedReader(new FileReader(file)); 

//Read the file 

и она отлично работает при запуске его в Eclipse, но если я экспортировать его в банку запустить его есть IllegalArgumentException:

Exception in thread "Thread-2" 
java.lang.IllegalArgumentException: URI is not hierarchical 

, и я действительно не знаю, почему, но с некоторыми тестирования я обнаружил, если я изменю

file = new File(getClass().getResource("/file.txt").toURI()); 

к

file = new File(getClass().getResource("/folder/file.txt").toURI()); 

, то он работает наоборот (она работает в банке, но не затмить).

Я использую Eclipse, и папка с моим файлом находится в папке класса.

+0

Если вы хотите прочитать файлы из каталога в банке с любые номера для файлов, см. [Stackoverflow-Link] (https://stackoverflow.com/questions/26185137/spring-boot-resource-not-found-when-using-executeable-jar/39818817#39818817) –

+0

Я не уверен, что исходный вопрос связан с весной. Ссылка в предыдущем комментарии ссылается на специальный ответ Spring от другого вопроса. Я считаю, что 'getResourceAsStream' по-прежнему является более простым и более переносимым решением проблемы. –

ответ

196

Вместо того, чтобы обратиться к ресурсу как File просто попросить ClassLoader вернуть InputStream для ресурса, а не с помощью getResourceAsStream:

InputStream in = getClass().getResourceAsStream("/file.txt"); 
BufferedReader reader = new BufferedReader(new InputStreamReader(in)); 

Пока file.txt ресурс доступен на пути к классам, этот подход будет работать одинаково независимо от того, находится ли ресурс file.txt в каталоге classes/ или внутри jar.

URI is not hierarchical происходит потому, что URI для ресурса в файле jar будет выглядеть примерно так: file:/example.jar!/file.txt. Вы не можете прочитать записи в файле jar (файл zip), как будто это был простой старый File.

Это объясняется также ответами на:

+2

Спасибо, это было очень полезно, и код работает отлично, но у меня есть одна проблема, мне нужно определить, существует ли 'InputStream' (например,' File.exists() '), поэтому моя игра может определить, следует ли использовать файл по умолчанию или нет. Благодарю. – PrinceCJC

+1

О, и BTW причина 'getClass(). GetResource (" **/folder **/file.txt ")' заставил его работать, потому что у меня была эта папка в том же каталоге, что и моя jar :). – PrinceCJC

+1

'getResourceAsStream' возвращает null, если ресурс не существует, так что это может быть ваш тест« существует ». –

10

Если вы хотите читать файл, я считаю, что еще есть подобное решение:

ClassLoader classLoader = getClass().getClassLoader(); 
    File file = new File(classLoader.getResource("file/test.xml").getFile()); 
+3

URL.getFile() * не конвертирует URL в имя файла. Он возвращает часть URL-адреса после хоста, при этом все процентные кодировки остаются нетронутыми, поэтому, если в пути содержатся любые символы, отличные от ASCII, или любые символы ASCII, которые не разрешены в URL-адресах (включая пробелы), результат не будет именем существующего файла , даже если URL-адрес является «файлом:». – VGR

+4

это не работает внутри, когда программа построена на банке –

1

Вы также можете использовать java.nio. Вот пример чавкать в тексте из файла на resourcePath в пути к классам:

new String(Files.readAllBytes(Paths.get(getClass().getResource(resourcePath).toURI()))) 
+3

URI, ссылающийся на ресурс внутри файла .jar, не является '' '' '' '' URI, поэтому ваш вызов Paths.get завершится неудачно. – VGR

+0

работал для меня :) – Lital

+9

Это действительно не удастся, если ресурс находится внутри файла jar. Мне любопытно, знает ли кто-нибудь о надлежащем способе чтения из банки с использованием класса Files, как показано в этом примере, то есть не используется «входной поток». –

6

Для доступа к файлу в банке у вас есть два варианта:

  • Поместите файл в структуре каталогов, соответствующих Вашему имя пакета (после извлечения файла .jar, он должен находиться в том же каталоге, что и файл .class), а затем получить его, используя getClass().getResourceAsStream("file.txt")

  • Поместите файл в корень (после извлечения.баночка файл, он должен находиться в корневом каталоге), то доступ к нему с помощью Thread.currentThread().getContextClassLoader().getResourceAsStream("file.txt")

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

1

Убедитесь, что вы работаете с правильным разделителем. Я заменил все / на относительный путь с помощью File.separator. Это отлично работало в среде IDE, однако не работало в JAR сборки.

0

Если вы используете весной, то вы можете использовать следующий метод для чтения файлов из SRC/основные/ресурсов:

import java.io.BufferedReader; 
import java.io.IOException; 
import java.io.InputStream; 
import java.io.InputStreamReader; 
import org.springframework.core.io.ClassPathResource; 

public String readFile() { 

    StringBuilder result = new StringBuilder(""); 
    ClassPathResource resource = new ClassPathResource("filename.txt"); 

    try (InputStream inputStream = resource.getInputStream()) { 

     BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream)); 
     String line; 

     while ((line = bufferedReader.readLine()) != null) { 
      result.append(line); 
     } 
     inputStream.close(); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } 
    return result.toString(); 
} 
+0

Добро пожаловать в SO. Это не дает ответа на вопрос. Как только у вас будет достаточно [репутации] (http: // stackoverflow.com/help/whats-Reputation), вы сможете [комментировать] (http://stackoverflow.com/help/privileges/comment) в любой записи. Также проверьте это [что я могу сделать вместо этого] (https://meta.stackexchange.com/questions/214173/why-do-i-need-50-reputation-to-comment-what-can-i-do-instead). – thewaywewere

1

Я имел эту проблему раньше, и я сделал запасной путь для загрузки. В основном первый способ работы с файлом .jar и вторым способом работает внутри eclipse или другой среды IDE.

public class MyClass { 

    public static InputStream accessFile() { 
     String resource = "my-file-located-in-resources.txt"; 

     // this is the path within the jar file 
     InputStream input = MyClass.class.getResourceAsStream("/resources/" + resource); 
     if (input == null) { 
      // this is how we load file within editor (eg eclipse) 
      input = MyClass.class.getClassLoader().getResourceAsStream(resource); 
     } 

     return input; 
    } 
} 
0

До сих пор (декабрь 2017), это единственное решение, которое я нашел, который работает как внутри и снаружи IDE.

Использование PathMatchingResourcePatternResolver

Примечание: работает также в весенне-ботинке

В этом примере я читал некоторые файлы, расположенные в SRC/главная/ресурсы/my_folder:

try { 
    // Get all the files under this inner resource folder: my_folder 
    String scannedPackage = "my_folder/*"; 
    PathMatchingResourcePatternResolver scanner = new PathMatchingResourcePatternResolver(); 
    Resource[] resources = scanner.getResources(scannedPackage); 

    if (resources == null || resources.length == 0) 
     log.warn("Warning: could not find any resources in this scanned package: " + scannedPackage); 
    else { 
     for (Resource resource : resources) { 
      log.info(resource.getFilename()); 
      // Read the file content (I used BufferedReader, but there are other solutions for that): 
      BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(resource.getInputStream())); 
      String line = null; 
      while ((line = bufferedReader.readLine()) != null) { 
       // ... 
       // ...      
      } 
      bufferedReader.close(); 
     } 
    } 
} catch (Exception e) { 
    throw new Exception("Failed to read the resources folder: " + e.getMessage(), e); 
} 
Смежные вопросы