Extração de recursos do Jar para o sistema de arquivos local

Às vezes, os recursos embutidos em seu .jar precisam ser extraídos para o sistema de arquivos do cliente. Exemplos disso são executáveis ​​e fontes (o SWT só pode carregar fontes do sistema de arquivos local).

Aqui está uma classe que irá extrair arquivos de dentro de seu jar, colocá-los em um diretório temporário, retornar o caminho do arquivo temporário e até mesmo remover os arquivos após a saída do Java VirtualMachine.

Para usar a classe, algo assim funciona:

String filePath = ResourceManager.extract("/com/dennisskinner/testapp/img/face.png");

Observe que o uso de caminhos absolutos é muito necessário por motivos de sanidade, no entanto, você pode usar um caminho relativo do local do ResourceManager, mas isso não é recomendado.

Finalmente, aqui está o ResourceManager.

import javax.swing.*;
import java.io.*;
import java.util.HashMap;
import java.util.Hashtable;
import java.util.Map;
import java.util.function.BiConsumer;

public class ResourceManager {

// Stores paths to files with the global jarFilePath as the key
private static Hashtable<String, String> fileCache = new Hashtable<String, String>();

/**
* Extract the specified resource from inside the jar to the local file system.

* @param jarFilePath absolute path to the resource

* @return full file system path if file successfully extracted, else null on error

*/

public static String extract(String jarFilePath){

if(jarFilePath == null)
return null;

// See if we already have the file
if(fileCache.contains(jarFilePath))
return fileCache.get(jarFilePath);

// Alright, we don't have the file, let's extract it
try {
// Read the file we're looking for
InputStream fileStream = ResourceManager.class.getResourceAsStream(jarFilePath);

// Was the resource found?
if(fileStream == null)
return null;

// Grab the file name
String[] chopped = jarFilePath.split("\/");
String fileName = chopped[chopped.length-1];

// Create our temp file (first param is just random bits)
File tempFile = File.createTempFile("asdf", fileName);

// Set this file to be deleted on VM exit
tempFile
.deleteOnExit();

// Create an output stream to barf to the temp file
OutputStream out = new FileOutputStream(tempFile);

// Write the file to the temp file
byte[] buffer = new byte[1024];
int len = fileStream.read(buffer);
while (len != -1) {
out.write(buffer, 0, len);
len
= fileStream.read(buffer);
}

// Store this file in the cache list
fileCache
.put(jarFilePath, tempFile.getAbsolutePath());

// Close the streams
fileStream
.close();
out.close();

// Return the path of this sweet new file
return tempFile.getAbsolutePath();

} catch (IOException e) {
return null;
}
}
}