这个想法相对简单。你有一些陷阱(比如如果文件已经存在该怎么办等等),但除此之外......
我先看看JarFile
(我在另一个例子的中间,但是当我有时间时,我会发布一些东西)
更新示例
public class JarTest {
protected static final String OUTPUT_PATH = "..."; // The place you want to extact the jar to
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
new JarTest();
}
public JarTest() {
try {
unjar();
// Copy new contents in...
jar();
} catch (IOException exp) {
exp.printStackTrace();
}
}
// This just recursivly lists through all the files to be included in the new jar
// We don't care about the directories, as we will create them from the file
// references in the Jar ourselves
protected List<File> getFiles(File path) {
List<File> lstFiles = new ArrayList<File>(25);
// If you want the directories, add the "path" to the list now...
File[] files = path.listFiles();
if (files != null && files.length > 0) {
for (File file : files) {
if (file.isDirectory()) {
lstFiles.addAll(getFiles(file));
} else {
lstFiles.add(file);
}
}
}
return lstFiles;
}
// Re-Jar the contents
// You should always attempt to jar back to a new file, as you may not want to effect the original ;)
public void jar() throws IOException {
JarOutputStream jos = null;
try {
String outputPath = OUTPUT_PATH;
// Create a new JarOutputStream to the file you want to create
jos = new JarOutputStream(new FileOutputStream("...")); // Add your file reference
List<File> fileList = getFiles(new File(OUTPUT_PATH));
System.out.println("Jaring " + fileList.size() + " files");
// Okay, I cheat. I make a list of all the paths already added to the Jar only create
// them when I need to. You could use "file.isDirectory", but that would mean you would need
// to ensure that the files were sorted to allow all the directories to be first
// or make sure that the directory reference is added to the start of each recursion list
List<String> lstPaths = new ArrayList<String>(25);
for (File file : fileList) {
// Replace the Windows file seperator
// We only want the path to this element
String path = file.getParent().replace("\\", "/");
// Get the name of the file
String name = file.getName();
// Remove the output path from the start of the path
path = path.substring(outputPath.length());
// Remove the leading slash if it exists
if (path.startsWith("/")) {
path = path.substring(1);
}
// Add the path path reference to the Jar
// A JarEntry is considered to be a directory if it ends with "/"
if (path.length() > 0) {
// At the trailing path seperator
path += "/";
// Check to see if we've already added it out not
if (!lstPaths.contains(path)) {
// At the path entry...we need need this to make it easier to
// extract the files at a later state. There is a way to cheat,
// but I'll let you figure it out
JarEntry entry = new JarEntry(path);
jos.putNextEntry(entry);
jos.closeEntry();
// Make sure we don't try to add the same path entry again
lstPaths.add(path);
}
}
System.out.println("Adding " + path + name);
// Create the actual entry for this file
JarEntry entry = new JarEntry(path + name);
jos.putNextEntry(entry);
// Write the entry to the file
FileInputStream fis = null;
try {
fis = new FileInputStream(file);
byte[] byteBuffer = new byte[1024];
int bytesRead = -1;
while ((bytesRead = fis.read(byteBuffer)) != -1) {
jos.write(byteBuffer, 0, bytesRead);
}
jos.flush();
} finally {
try {
fis.close();
} catch (Exception e) {
}
}
jos.closeEntry();
}
jos.flush();
} finally {
try {
jos.close();
} catch (Exception e) {
}
}
}
public void unjar() throws IOException {
JarFile jarFile = null;
try {
String outputPath = OUTPUT_PATH;
File outputPathFile = new File(outputPath);
// Make the output directories.
// I'll leave it up to you to decide how best to deal with existing content ;)
outputPathFile.mkdirs();
// Create a new JarFile reference
jarFile = new JarFile(new File("C:/hold/Java_Harmony.jar"));
// Get a list of all the entries
Enumeration<JarEntry> entries = jarFile.entries();
while (entries.hasMoreElements()) {
// Get the next entry
JarEntry entry = entries.nextElement();
// Make a file reference
File path = new File(outputPath + File.separator + entry.getName());
if (entry.isDirectory()) {
// Make the directory structure if we can
if (!path.exists() && !path.mkdirs()) {
throw new IOException("Failed to create output path " + path);
}
} else {
System.out.println("Extracting " + path);
// Extract the file from the Jar and write it to disk
InputStream is = null;
OutputStream os = null;
try {
is = jarFile.getInputStream(entry);
os = new FileOutputStream(path);
byte[] byteBuffer = new byte[1024];
int bytesRead = -1;
while ((bytesRead = is.read(byteBuffer)) != -1) {
os.write(byteBuffer, 0, bytesRead);
}
os.flush();
} finally {
try {
os.close();
} catch (Exception e) {
}
try {
is.close();
} catch (Exception e) {
}
}
}
}
} finally {
try {
jarFile.close();
} catch (Exception e) {
}
}
}
}