57

jarファイルからファイルをコピーしたい。コピーするファイルは、作業ディレクトリの外にコピーされます。私はいくつかのテストを行いました、そして私が試みるすべての方法は0バイトのファイルで終わります。

編集:ファイルのコピーを手動ではなくプログラムを介して実行したい。

4

9 に答える 9

60

まず最初に、以前に投稿されたいくつかの回答は完全に正しいと言いたいのですが、GPLの下でオープンソースライブラリを使用できない場合があるため、またはjarXDなどをダウンロードするのが面倒なために私に伝えたいと思いますあなたの理由はここにありますスタンドアロンソリューションです。

以下の関数は、Jarファイルの横にあるリソースをコピーします。

  /**
     * Export a resource embedded into a Jar file to the local file path.
     *
     * @param resourceName ie.: "/SmartLibrary.dll"
     * @return The path to the exported resource
     * @throws Exception
     */
    static public String ExportResource(String resourceName) throws Exception {
        InputStream stream = null;
        OutputStream resStreamOut = null;
        String jarFolder;
        try {
            stream = ExecutingClass.class.getResourceAsStream(resourceName);//note that each / is a directory down in the "jar tree" been the jar the root of the tree
            if(stream == null) {
                throw new Exception("Cannot get resource \"" + resourceName + "\" from Jar file.");
            }

            int readBytes;
            byte[] buffer = new byte[4096];
            jarFolder = new File(ExecutingClass.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath()).getParentFile().getPath().replace('\\', '/');
            resStreamOut = new FileOutputStream(jarFolder + resourceName);
            while ((readBytes = stream.read(buffer)) > 0) {
                resStreamOut.write(buffer, 0, readBytes);
            }
        } catch (Exception ex) {
            throw ex;
        } finally {
            stream.close();
            resStreamOut.close();
        }

        return jarFolder + resourceName;
    }

ExecutingClassをクラスの名前に変更し、次のように呼び出します。

String fullPath = ExportResource("/myresource.ext");

Java 7+用に編集(便宜上)

GOXR3PLUSが回答し、 Andy Thomasが指摘したように、これは次の方法で実現できます。

Files.copy( InputStream in, Path target, CopyOption... options)

詳細については、 GOXR3PLUSの回答を参照してください

于 2012-11-14T13:29:51.543 に答える
39

0バイトのファイルについてのコメントを考えると、これをプログラムで実行しようとしていること、およびタグを指定してJavaで実行していることを前提としています。それが当てはまる場合は、Class.getResource()を使用してJAR内のファイルを指すURLを取得し、次にApache Commons IO FileUtils.copyURLToFile()を使用してファイルシステムにコピーします。例えば:

URL inputUrl = getClass().getResource("/absolute/path/of/source/in/jar/file");
File dest = new File("/path/to/destination/file");
FileUtils.copyURLToFile(inputUrl, dest);

ほとんどの場合、現在使用しているコードの問題は、バッファリングされた出力ストリームを使用してファイルに書き込みを行っているが、ファイルを閉じられていないことです。

ああ、質問を編集して、これをどのように実行したいかを正確に明確にする必要があります(プログラムではなく、言語など)。

于 2012-04-25T01:43:36.717 に答える
17

Java 7以降でそれを行うためのより高速な方法に加えて、現在のディレクトリを取得するためのコード:

   /**
     * Copy a file from source to destination.
     *
     * @param source
     *        the source
     * @param destination
     *        the destination
     * @return True if succeeded , False if not
     */
    public static boolean copy(InputStream source , String destination) {
        boolean succeess = true;

        System.out.println("Copying ->" + source + "\n\tto ->" + destination);

        try {
            Files.copy(source, Paths.get(destination), StandardCopyOption.REPLACE_EXISTING);
        } catch (IOException ex) {
            logger.log(Level.WARNING, "", ex);
            succeess = false;
        }

        return succeess;

    }

テストします(icon.pngはアプリケーションのパッケージイメージ内のイメージです):

copy(getClass().getResourceAsStream("/image/icon.png"),getBasePathForClass(Main.class)+"icon.png");

コード行について(getBasePathForClass(Main.class)):->ここに追加した答えを確認してください:)-> Javaで現在の作業ディレクトリを取得する

于 2017-05-19T19:10:42.890 に答える
14

Java 8(実際には、ファイルシステムは1.7以降にあります)には、これに対処するためのいくつかのクールな新しいクラス/メソッドが付属しています。JARは基本的にZIPファイルであると誰かがすでに述べたように、

final URI jarFileUril = URI.create("jar:file:" + file.toURI().getPath());
final FileSystem fs = FileSystems.newFileSystem(jarFileUri, env);

Zipファイルを参照)

次に、次のような便利な方法の1つを使用できます。

fs.getPath("filename");

次に、Filesクラスを使用できます

try (final Stream<Path> sources = Files.walk(from)) {
     sources.forEach(src -> {
         final Path dest = to.resolve(from.relativize(src).toString());
         try {
            if (Files.isDirectory(from)) {
               if (Files.notExists(to)) {
                   log.trace("Creating directory {}", to);
                   Files.createDirectories(to);
               }
            } else {
                log.trace("Extracting file {} to {}", from, to);
                Files.copy(from, to, StandardCopyOption.REPLACE_EXISTING);
            }
       } catch (IOException e) {
           throw new RuntimeException("Failed to unzip file.", e);
       }
     });
}

注:テスト用にJARファイルを解凍しようとしました

于 2015-04-15T20:09:38.570 に答える
5

堅牢なソリューション:

public static void copyResource(String res, String dest, Class c) throws IOException {
    InputStream src = c.getResourceAsStream(res);
    Files.copy(src, Paths.get(dest), StandardCopyOption.REPLACE_EXISTING);
}

次のように使用できます。

File tempFileGdalZip = File.createTempFile("temp_gdal", ".zip");
copyResource("/gdal.zip", tempFileGdalZip.getAbsolutePath(), this.getClass());
于 2018-10-19T12:56:22.057 に答える
2

JarInputStreamクラスを使用します。

// assuming you already have an InputStream to the jar file..
JarInputStream jis = new JarInputStream( is );
// get the first entry
JarEntry entry = jis.getNextEntry();
// we will loop through all the entries in the jar file
while ( entry != null ) {
  // test the entry.getName() against whatever you are looking for, etc
  if ( matches ) {
    // read from the JarInputStream until the read method returns -1
    // ...
    // do what ever you want with the read output
    // ...
    // if you only care about one file, break here 
  }
  // get the next entry
  entry = jis.getNextEntry();
}
jis.close();

参照:JarEntry

于 2012-04-25T02:23:00.320 に答える
0

jarから外部にファイルをコピーするには、次のアプローチを使用する必要があります。

  1. InputStream使用してjarファイル内のファイルにアクセスしますgetResourceAsStream()
  2. を使用してターゲットファイルを開きますFileOutputStream
  3. 入力から出力ストリームにバイトをコピーします
  4. リソースリークを防ぐためにストリームを閉じます

既存の値を置き換えない変数も含むサンプルコード:

public File saveResource(String name) throws IOException {
    return saveResource(name, true);
}

public File saveResource(String name, boolean replace) throws IOException {
    return saveResource(new File("."), name, replace)
}

public File saveResource(File outputDirectory, String name) throws IOException {
    return saveResource(outputDirectory, name, true);
}

public File saveResource(File outputDirectory, String name, boolean replace)
       throws IOException {
    File out = new File(outputDirectory, name);
    if (!replace && out.exists()) 
        return out;
    // Step 1:
    InputStream resource = this.getClass().getResourceAsStream(name);
    if (resource == null)
       throw new FileNotFoundException(name + " (resource not found)");
    // Step 2 and automatic step 4
    try(InputStream in = resource;
        OutputStream writer = new BufferedOutputStream(
            new FileOutputStream(out))) {
         // Step 3
         byte[] buffer = new byte[1024 * 4];
         int length;
         while((length = in.read(buffer)) >= 0) {
             writer.write(buffer, 0, length);
         }
     }
     return out;
}
于 2016-02-26T17:33:58.467 に答える
-1

jarファイルは単なるzipファイルです。(使い慣れた方法を使用して)解凍し、通常どおりファイルをコピーします。

于 2012-04-25T01:32:55.157 に答える
-2
${JAVA_HOME}/bin/jar -cvf /path/to.jar
于 2012-04-25T01:34:39.383 に答える