2016-03-26 1 views
3

Я потратил часы и часы на поиск ответа, и я просто не могу понять это, я пытаюсь скопировать папку ресурсов, содержащую все изображения и файлы данных для моей игры я работаю из бегущей банки и в E:/Program Files/mtd/Она отлично работает, когда я запускаю ее из затмения, но когда я экспортирую банку и ее пытаюсь, я получаю NoSuchFileExceptionКак скопировать папку ресурсов из jar в файлы программы

`JAR 
Installing... 
file:///C:/Users/Cam/Desktop/mtd.jar/resources to file:///E:/Program%20Files/mtd 
/resources 
java.nio.file.NoSuchFileException: C:\Users\Cam\Desktop\mtd.jar\resources 
     at sun.nio.fs.WindowsException.translateToIOException(Unknown Source) 
     at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source) 
     at sun.nio.fs.WindowsException.rethrowAsIOException(Unknown Source) 
     at sun.nio.fs.WindowsFileAttributeViews$Basic.readAttributes(Unknown Sou 
rce) 
     at sun.nio.fs.WindowsFileAttributeViews$Basic.readAttributes(Unknown Sou 
rce) 
     at sun.nio.fs.WindowsFileSystemProvider.readAttributes(Unknown Source) 
     at java.nio.file.Files.readAttributes(Unknown Source) 
     at java.nio.file.FileTreeWalker.walk(Unknown Source) 
     at java.nio.file.FileTreeWalker.walk(Unknown Source) 
     at java.nio.file.Files.walkFileTree(Unknown Source) 
     at java.nio.file.Files.walkFileTree(Unknown Source) 
     at me.Zacx.mtd.main.Game.<init>(Game.java:94) 
     at me.Zacx.mtd.main.Game.main(Game.java:301)` 

Это код, я использую:

if (!pfFolder.exists()) { 
    pfFolder.mkdir(); 
    try { 

     URL url = getClass().getResource("/resources/"); 
     URI uri = null; 

     if (url.getProtocol().equals("jar")) { 
      System.out.println("JAR"); 
      JarURLConnection connect = (JarURLConnection) url.openConnection(); 
      uri = new URI(connect.getJarFileURL().toURI().toString() + "/resources/"); 

     } else if (url.getProtocol().equals("file")) { 
      System.out.println("FILE"); 
      uri = url.toURI(); 
     } 

     final Path src = Paths.get(uri); 
     final Path tar = Paths.get(System.getenv("ProgramFiles") + "/mtd/resources/"); 

     System.out.println("Installing..."); 
     System.out.println(src.toUri() + " to " + tar.toUri()); 

     Files.walkFileTree(src, new SimpleFileVisitor<Path>() { 
      public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 
       return copy(file); 
      } 
      public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { 
       return copy(dir); 
      } 
      private FileVisitResult copy(Path fileOrDir) throws IOException { 
       System.out.println("Copying " + fileOrDir.toUri() + " to " + tar.resolve(src.relativize(fileOrDir)).toUri()); 
       Files.copy(fileOrDir, tar.resolve(src.relativize(fileOrDir))); 
       return FileVisitResult.CONTINUE; 
      } 
     }); 
     System.out.println("Done!"); 
    } catch (IOException e) { 
     e.printStackTrace(); 
    } catch (URISyntaxException e) { 
     e.printStackTrace(); 
    } 
} 
+0

'% 20' является HTML-спаслось пространство , это то, что дает вам проблемы (вероятно, происходит из кодировки URL через '.toUri()')? Где именно строка 94? '(Game.java:94)' Is 'C: \ Users \ Cam \ Desktop \ mtd.jar \ resources' папка или файл? –

+0

@MaximilianGerhardt using .replaceAll (...), чтобы удалить% 20s, не исправляет его, Game.java:94 - Files.walkFileTree (src, new SimpleFileVisitor () {и ресурсы - это папка, содержащая все изображения и т. д. для моей игры. Извините за то, что не в том числе:/ – Zacx

+0

Итак, не является ли Java правильным, говоря «java.nio.file.NoSuchFileException: C: \ Users \ Cam \ Desktop \ mtd.jar \ resources', потому что' \ resources' действительно папка и никакой каталог? Должна быть некоторая ошибка в способе, по которому вы ходите по дереву файлов. Может быть, попробуйте создать сначала создать папку? Функция 'copy()', похоже, не называется , или иначе мы увидим строку «Копирование .. в ...» * ИЛИ *, это сбой в этой точной строке 'System.out.println()' в '.resolve()' или 'relativize()' добавьте еще вывод отладки, чтобы убедиться. –

ответ

-1

I Finally Found ОТВЕТ Я не хочу, чтобы впечатать большое, длинное объяснение, но и для тех, кто ищет решения, здесь

` 
       //on startup 
       installDir(""); 
       for (int i = 0; i < toInstall.size(); i++) { 
        File f = toInstall.get(i); 
        String deepPath = f.getPath().replace(f.getPath().substring(0, f.getPath().lastIndexOf("resources") + "resources".length() + 1), ""); 
        System.out.println(deepPath); 
        System.out.println("INSTALLING: " + deepPath); 
        installDir(deepPath); 
        System.out.println("INDEX: " + i); 
       } 

public void installDir(String path) { 
      System.out.println(path); 
      final URL url = getClass().getResource("/resources/" + path); 
      if (url != null) { 
       try { 
        final File apps = new File(url.toURI()); 
        for (File app : apps.listFiles()) { 
         System.out.println(app); 
          System.out.println("copying..." + app.getPath() + " to " + pfFolder.getPath()); 
          String deepPath = app.getPath().replace(app.getPath().substring(0, app.getPath().lastIndexOf("resources") + "resources".length() + 1), ""); 
          System.out.println(deepPath); 

         try { 

           File f = new File(resources.getPath() + "/" + deepPath); 
           if (getExtention(app) != null) { 
           FileOutputStream resourceOS = new FileOutputStream(f); 
           byte[] byteArray = new byte[1024]; 
           int i; 
           InputStream classIS = getClass().getClassLoader().getResourceAsStream("resources/" + deepPath); 
         //While the input stream has bytes 
           while ((i = classIS.read(byteArray)) > 0) 
           { 
         //Write the bytes to the output stream 
            resourceOS.write(byteArray, 0, i); 
           } 
         //Close streams to prevent errors 
           classIS.close(); 
           resourceOS.close(); 
           } else { 
            System.out.println("new dir: " + f.getPath() + " (" + toInstall.size() + ")"); 
            f.mkdir(); 
            toInstall.add(f); 
            System.out.println(toInstall.size()); 
           } 
         } catch (IOException e) { 
          e.printStackTrace(); 
         } 
        } 
       } catch (URISyntaxException ex) { 
        // never happens 
       } 
      } 

     }` 
1

EDITED (полностью переписана для ясности, пример кода)

Проблема здесь в разные файловые системы. C:/Users/Cam/Desktop/mtd.jar - File в WindowsFileSystem. Поскольку это файл, а не каталог, вы не можете получить доступ к подкаталогу внутри файла; C:/Users/Cam/Desktop/mtd.jar/resources действителен только Path, если mtd.jar фактически является вместо file.

Чтобы получить доступ к чему-либо в другой файловой системе, вы должны использовать путь из корня этой файловой системы. Например, если у вас есть файл в D:\dir1\dir2\file, вы не можете связаться с ним, используя путь, начинающийся с C:\ (символические ссылки не выдерживают); вы должны использовать путь, который начинается с корня этой файловой системы D:\.

Файл jar - это всего лишь файл. Он может быть расположен в любом месте файловой системы и может быть перемещен, скопирован или удален как обычный файл. Однако он содержит в себе собственную файловую систему. Нет пути к окну, который может использоваться для ссылки на любой файл в файловой системе jar, так же как ни один путь, начинающийся с C:\, не может ссылаться на любой файл в файловой системе D:\.

Для доступа к содержимому баночки вы должны открыть банку как ZipFileSystem.

// Autoclose the file system at end of try { ... } block. 
try(FileSystem zip_fs = FileSystems.newFileSystem(pathToZipFile, null)) { 
} 

После того как вы zip_fs, вы можете использовать zip_fs.getPath("/path/in/zip");, чтобы получить Path к файлу в нем. Этот объект Path фактически будет объектом пути ZipFileSystemProvider, а не объектом пути WindowsFileSystemProvider, но в остальном это объект Path, который можно открыть, прочитать и т. Д., По крайней мере, до тех пор, пока не будет закрыт ZipFileSystem. Наибольшие различия заключаются в том, что path.getFileSystem() вернет ZipFileSystem и что resolve() и relativize() не могут использовать объекты пути, где getFileSystem() возвращает разные файловые системы.

Когда ваш проект проходил от Eclipse, все ресурсы находились в WindowsFileSystem, поэтому перемещение дерева файловой системы и копирование ресурсов было прямолинейным. Когда ваш проект запускался из банки, ресурсы не были в файловой системе по умолчанию.

Вот класс Java, который скопирует ресурсы в каталог установки. Он будет работать в Eclipse (со всеми ресурсами как отдельные файлы), а также когда приложение будет упаковано в банку.

public class Installer extends SimpleFileVisitor<Path> { 

    public static void installResources(Path dst, Class<?> cls, String root) throws URISyntaxException, IOException { 
     URL location = cls.getProtectionDomain().getCodeSource().getLocation(); 
     if (location.getProtocol().equals("file")) { 
      Path path = Paths.get(location.toURI()); 
      if (location.getPath().endsWith(".jar")) { 
       try (FileSystem fs = FileSystems.newFileSystem(path, null)) { 
        installResources(dst, fs.getPath("/" + root)); 
       } 
      } else { 
       installResources(dst, path.resolve(root)); 
      } 
     } else { 
      throw new IllegalArgumentException("Not supported: " + location); 
     } 
    } 

    private static void installResources(Path dst, Path src) throws IOException { 
     Files.walkFileTree(src, new Installer(dst, src)); 
    } 

    private final Path target, source; 

    private Installer(Path dst, Path src) { 
     target = dst; 
     source = src; 
    } 

    private Path resolve(Path path) { 
     return target.resolve(source.relativize(path).toString()); 
    } 

    @Override 
    public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException { 
     Path dst = resolve(dir); 
     Files.createDirectories(dst); 
     return super.preVisitDirectory(dir, attrs); 
    } 

    @Override 
    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { 
     Path dst = resolve(file); 
     Files.copy(Files.newInputStream(file), dst, StandardCopyOption.REPLACE_EXISTING); 
     return super.visitFile(file, attrs); 
    } 
} 

Вызывается как:

Path dst = Paths.get("C:\\Program Files\\mtd"); 
    Installer.installResources(dst, Game.class, "resources"); 
+0

Когда я пытаюсь это решение, я получаю этот вывод 'file: /// C:/Users/Cam/Desktop/eclipse/Work/Meme% 20Tower% 20Defence/bin/to file : /// E:/Program% 20Files/mtd/resources файл:/C:/Users/Cam/Desktop/eclipse/Work/Meme% 20Tower% 20Defence/bin/ Исключение в теме "main" java.nio. file.ProviderNotFoundException: поставщик не найден. Текущий код: 'System.out.println (src.toUri() +" to "+ tar.Touri()); \t \t \t \t System.out.println (uri); \t \t \t \t попытка (FileSystem фс = FileSystems.newFileSystem (Paths.get (URI), нуль)) { \t \t \t \t путь Path = fs.getPath ("/ ресурсы /"); ? \t \t \t \t \t \t \t Files.walkFileTree (путь, новый SimpleFileVisitor () { ' – Zacx

+0

У вас есть' uri' к банку Попробуйте 'FileSystems.newFileSystem (Uri, новый HashMap <>());' версия звонка – AJNeufeld

+0

Я не уверен, что вы подразумеваете под этим, не могли бы вы подробнее рассказать? Еще раз, я новичок в файловых системах. – Zacx

0

Это было сложнее, чем я думал, но вот как это сделать.

вот мой метод Копированию https://examples.javacodegeeks.com/core-java/io/file/4-ways-to-copy-file-in-java/

public void copyFile(String inputPath, String outputPath) throws IOException 
{ 

    InputStream inputStream = null; 

    OutputStream outputStream = null; 
    try { 

     inputStream = getClass().getResourceAsStream(inputPath); 
     outputStream = new FileOutputStream(outputPath); 

     byte[] buf = new byte[1024]; 

     int bytesRead; 

     while ((bytesRead = inputStream.read(buf)) > 0) { 

      outputStream.write(buf, 0, bytesRead); 

     } 

    } 
    finally { 


     inputStream.close(); 

     outputStream.close(); 

    } 

Обратите внимание на структуру проекта файла Jar в этом образе Project structure

Теперь мне нужно прочитать файл Jar. Это изменение на этом решении How can I get a resource "Folder" from inside my jar File?. Оба эти метода работают вместе для получения результата. Я тестировал это, и он работает.

общественного класса Main {

public static void main(String[] args) throws IOException { 
    // TODO Auto-generated method stub 

    final String pathPartOne = "test/com"; 
    final String pathPartTwo = "/MyResources"; 
    String pathName = "C:\\Users\\Jonathan\\Desktop\\test.jar"; 

    JarTest test = new JarTest(); 

    final File jarFile = new File(pathName); 

    if(jarFile.isFile()) { // Run with JAR file 
     final JarFile jar = new JarFile(jarFile); 
     final Enumeration<JarEntry> entries = jar.entries(); //gives ALL entries in jar 
     while(entries.hasMoreElements()) { 
      final String name = entries.nextElement().getName(); 

      if (name.startsWith(pathPartOne+pathPartTwo + "/")) { //filter according to the path 
       if(name.contains("."))//has extension 
       { 
        String relavtivePath = name.substring(pathPartOne.length()+1); 
        String fileName = name.substring(name.lastIndexOf('/')+1); 
        System.out.println(relavtivePath); 
        System.out.println(fileName); 
        test.copyFile(relavtivePath, "C:\\Users\\Jonathan\\Desktop\\" + fileName); 
       } 

      } 
     } 
     jar.close(); 
    } 


} 

}

Надежда, что помогает.

+0

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

+0

Да, но я считаю, что здесь применяется тот же принцип. Сначала вам нужно получить файл, который вы хотите скопировать, пройдя путь. Как только у вас есть путь, вы должны быть отсортированы. Я не верю, что «C: \ Users \ Cam \ Desktop \ mtd.jar \ resources» является допустимым путем –

+0

Теоретически это должен быть путь vaild, так как есть папка, называемая ресурсами внутри mtd.jar, извините, если я «Я полностью отключаюсь, я новичок в библиотеках файловых систем, и мне 14, поэтому у меня нет многолетнего опыта позади меня, что я могу использовать, чтобы понять это, к сожалению :( – Zacx

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

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