So I have been working with a Derby DB and can write to and work with the data. I'm now trying to pack it into a single archive file(jar). I can get it to pack and unpack with no issues. Well except one.
I can get it to pack into a jar but it has an extra folder depth. So if I pack up the directory that is named "December", and inside that archive I also get a "December" folder with the contents inside it. Is there a way I can remove that extra folder either in packing or unpacking?
I have tried to play with the file's name but if I mess with it I get errors saying it can't find the file after I renamed it. I tried this both before it's packed and while unpacking it. Closes I got was each file name in the main directory but all the files are 0kb. I even try to change the pack directory to "December*", but it didn't like that.
public class JarPack {
public static void pack(String name,String dir) throws FileNotFoundException, IOException{
System.out.println(dir);
Manifest manifest = new Manifest();
manifest.getMainAttributes().put(Attributes.Name.MANIFEST_VERSION, "1.0");
JarOutputStream target = new JarOutputStream(new FileOutputStream(name), manifest);
add(new File(dir), target);
target.close();
}
private static void add(File source, JarOutputStream target) throws IOException{
BufferedInputStream in = null;
try
{
if (source.isDirectory())
{
String name = source.getPath().replace("\\", "/");
if (!name.isEmpty())
{
if (!name.endsWith("/"))
name += "/";
JarEntry entry = new JarEntry(name);
entry.setTime(source.lastModified());
target.putNextEntry(entry);
target.closeEntry();
}
for (File nestedFile: source.listFiles())
add(nestedFile, target);
return;
}
JarEntry entry = new JarEntry(source.getPath().replace("\\", "/"));
entry.setTime(source.lastModified());
target.putNextEntry(entry);
in = new BufferedInputStream(new FileInputStream(source));
byte[] buffer = new byte[1024];
while (true)
{
int count = in.read(buffer);
if (count == -1)
break;
target.write(buffer, 0, count);
}
target.closeEntry();
}
finally{
if (in != null)
in.close();
}
}
#SuppressWarnings("resource")
public static void unPack(String name,String dir) throws java.io.IOException {
java.util.jar.JarFile jarfile = new java.util.jar.JarFile(new java.io.File(name));
java.util.Enumeration<java.util.jar.JarEntry> enu= jarfile.entries();
while(enu.hasMoreElements()){
String destdir = dir;
java.util.jar.JarEntry je = enu.nextElement();
if (!je.getName().equals("META-INF/MANIFEST.MF")){
java.io.File fl = new java.io.File(destdir, je.getName());
if(!fl.exists()){
fl.getParentFile().mkdirs();
fl = new java.io.File(destdir, je.getName());
}
if(je.isDirectory()){
continue;
}
java.io.InputStream is = jarfile.getInputStream(je);
java.io.FileOutputStream fo = new java.io.FileOutputStream(fl);
while(is.available()>0){
fo.write(is.read());
}
fo.close();
is.close();
}
}
}
}
I am not able delete file that is stored in cache. I am using the cache for several purposes. I am reading and writing but not able to delete. Can someone please help me with this?
//write
public static void writeObject(Context context, String key, Object object)
throws IOException {
Log.d("Cache", "WRITE: context");
FileOutputStream fos = context.openFileOutput(key, Context.MODE_PRIVATE);
ObjectOutputStream oos = new ObjectOutputStream(fos);
oos.writeObject(object);
oos.close();
fos.close();
}
//read
public static Object readObject(Context context, String key) throws IOException,
ClassNotFoundException {
FileInputStream fis = context.openFileInput(key);
ObjectInputStream ois = new ObjectInputStream(fis);
Object object = ois.readObject();
return object;
}
//delete
public static void clearCahe(String key) throws IOException,ClassNotFoundException {
File file = new File(key);
file.delete();
}
context.openFileOutput(key writes the file to internal memory. The path you can find with getFilesDir() and looks like /data/data/<yourpackagename>/files.
So if you want to delete the file 'key' you have to set up the path for File file = new File(path) as String path = getFilesDir().getAbsolutePath() + "/" + key;.
And use file.exists() to check if the file exists!
use this to clear application data.
public void clearApplicationData()
{
File cache = getCacheDir();
File appDir = new File(cache.getParent());
if (appDir.exists()) {
String[] children = appDir.list();
for (String s : children) {
if (!s.equals("lib")) {
deleteDir(new File(appDir, s));Log.i("TAG", "**************** File /data/data/APP_PACKAGE/" + s + " DELETED *******************");
}
}
}
}
public static boolean deleteDir(File dir)
{
if (dir != null && dir.isDirectory()) {
String[] children = dir.list();
for (int i = 0; i < children.length; i++) {
boolean success = deleteDir(new File(dir, children[i]));
if (!success) {
return false;
}
}
}
return dir.delete();
}
Files
Like the cache directory, your app also has an app-specific directory for holding files. Files in this directory will exist until the app explicitly deletes them or the app is uninstalled. You typically access this directory with Context.getFilesDir(). This can show up as various things on the app info screen, but in your screenshot this is "USB Storage Data".
NOTE: If you want to explicitly place on external media (typically SD card), you can use Context.getExternalFilesDir(String type).
Simple cache manager:
public class CacheManager {
private static final long MAX_SIZE = 5242880L; // 5MB
private CacheManager() {
}
public static void cacheData(Context context, byte[] data, String name) throws IOException {
File cacheDir = context.getCacheDir();
long size = getDirSize(cacheDir);
long newSize = data.length + size;
if (newSize > MAX_SIZE) {
cleanDir(cacheDir, newSize - MAX_SIZE);
}
File file = new File(cacheDir, name);
FileOutputStream os = new FileOutputStream(file);
try {
os.write(data);
}
finally {
os.flush();
os.close();
}
}
public static byte[] retrieveData(Context context, String name) throws IOException {
File cacheDir = context.getCacheDir();
File file = new File(cacheDir, name);
if (!file.exists()) {
// Data doesn't exist
return null;
}
byte[] data = new byte[(int) file.length()];
FileInputStream is = new FileInputStream(file);
try {
is.read(data);
}
finally {
is.close();
}
return data;
}
private static void cleanDir(File dir, long bytes) {
long bytesDeleted = 0;
File[] files = dir.listFiles();
for (File file : files) {
bytesDeleted += file.length();
file.delete();
if (bytesDeleted >= bytes) {
break;
}
}
}
private static long getDirSize(File dir) {
long size = 0;
File[] files = dir.listFiles();
for (File file : files) {
if (file.isFile()) {
size += file.length();
}
}
return size;
}
}
NOTE: The purpose of the cache is to cut down on network activity,
long processes, and provide a responsive UI in your app.
Reference: When to clear the cache dir in Android?.
I have a folder with 3 picture inside of them which I wish to zip and email. I have a method that does this which I've used with previous problems and it works fine. However this time it keeps generating an invalid zip and when I open the zip it only has 1 picture inside with a size of 0.
I can't seems to figure out why though. This is the method:
//generate the zip file for the picture
String zipFile = context.getExternalFilesDir(null) + "/ArcFlash/Checklist.zip";
String srcDir = context.getExternalFilesDir(null) + "/ArcFlash/CheckListMedia";
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
File srcFile = new File(srcDir);
addDirToArchive(zos, srcFile, context);
here is my addDirToArchive method which generates the zip:
private static void addDirToArchive(ZipOutputStream zos, File srcFile, Context ctx)
{
File[] files = srcFile.listFiles();
for (int i = 0; i < files.length; i++)
{
// if the file is directory, use recursion
if (files[i].isDirectory())
{
addDirToArchive(zos, files[i], ctx);
continue;
}
try
{
System.out.println("tAdding file: " + files[i].getName());
// create byte buffer
byte[] buffer = new byte[1024];//2048
FileInputStream fis = new FileInputStream(files[i]);
String target = ctx.getExternalFilesDir(null) + "/";
String oldPath = files[i].getPath();
String newPath = oldPath.replace(target, "");
zos.putNextEntry(new ZipEntry(newPath));
int length;
while ((length = fis.read(buffer)) > 0)
{
zos.write(buffer, 0, length);
}
zos.closeEntry();
// close the InputStream
fis.close();
}
catch (Exception ex)
{
Log.i("customException", "error zipping: " + ex.getMessage());
}
}
}
EDIT
Using the code samples below, here is how to do what you want:
final Path basePath = Paths.get(context.getExternalFilesDir(null));
final Path srcDir = Paths.resolve("ArcFlash/CheckListMedia");
final Path zipFile = Paths.resolve("ArcFlash/Checklist.zip");
final Map<String, Object> env = new HashMap<>();
env.put("create", "true");
final URI zip = URI.create("jar:file:" + zipFile.toAbsolutePath().toString());
try (
final FileSystem fs = FileSystems.newFileSystem(zip, env, null);
) {
Files.walkFileTree(srcDir, new CopyFileVisitor(srcDir, fs.getPath("/")));
}
First, a sample of how to create a zip file:
public final class ZipZip
{
public static void main(final String... args)
throws IOException
{
final Map<String, Object> env = new HashMap<>();
env.put("create", "true");
final URI zip = URI.create("jar:file:/tmp/t.zip");
final Path sourceFile = Paths.get("/tmp/foo.txt");
Files.deleteIfExists(Paths.get("/tmp/t.zip"));
try (
final FileSystem fs = FileSystems.newFileSystem(zip, env, null);
) {
final Path zipdir = fs.getPath("/dir");
Files.createDirectory(zipdir);
final Path zipfile = zipdir.resolve("t.txt");
Files.copy(sourceFile, zipfile);
}
}
}
Then, I have recently written a FileVisitor to recursively copy a directory, which is used here; here is its code:
public final class CopyFileVisitor
implements FileVisitor<Path>
{
private final Path srcdir;
private final Path dstdir;
public CopyFileVisitor(final Path srcdir, final Path dstdir)
{
this.srcdir = srcdir.toAbsolutePath();
this.dstdir = dstdir.toAbsolutePath();
}
#Override
public FileVisitResult preVisitDirectory(final Path dir,
final BasicFileAttributes attrs)
throws IOException
{
Files.createDirectories(toDestination(dir));
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult visitFile(final Path file,
final BasicFileAttributes attrs)
throws IOException
{
System.out.printf("%s -> %s\n", file.toAbsolutePath(),
toDestination(file));
Files.copy(file, toDestination(file));
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult visitFileFailed(Path file, IOException exc)
throws IOException
{
throw exc;
}
#Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc)
throws IOException
{
if (exc != null)
throw exc;
return FileVisitResult.CONTINUE;
}
private Path toDestination(final Path victim)
{
final Path tmp = victim.toAbsolutePath();
final Path rel = srcdir.relativize(tmp);
return dstdir.resolve(rel.toString());
}
}
I strongly recommend you to use this library for zipping/unzipping contents:
http://www.lingala.net/zip4j/
Be sure you are adding correct headers while making the file.
Suppose I have the following directory structure.
D:\reports\january\
Inside january there are suppose two excel files say A.xls and B.xls. There are many places where it has been written about how to zip files using java.util.zip. But I want to zip the january folder itself inside reports folder so that both january and january.zip will be present inside reports. (That means when I unzip the january.zip file I should get the january folder).
Can anyone please provide me the code to do this using java.util.zip. Please let me know whether this can be more easily done by using other libraries.
Thanks a lot...
Have you tried Zeroturnaround Zip library? It's really neat! Zip a folder is just a one liner:
ZipUtil.pack(new File("D:\\reports\\january\\"), new File("D:\\reports\\january.zip"));
(thanks to Oleg Ĺ elajev for the example)
Here is the Java 8+ example:
public static void pack(String sourceDirPath, String zipFilePath) throws IOException {
Path p = Files.createFile(Paths.get(zipFilePath));
try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(p))) {
Path pp = Paths.get(sourceDirPath);
Files.walk(pp)
.filter(path -> !Files.isDirectory(path))
.forEach(path -> {
ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString());
try {
zs.putNextEntry(zipEntry);
Files.copy(path, zs);
zs.closeEntry();
} catch (IOException e) {
System.err.println(e);
}
});
}
}
It can be easily solved by package java.util.Zip no need any extra Jar files
Just copy the following code and run it with your IDE
//Import all needed packages
package general;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class ZipUtils {
private List <String> fileList;
private static final String OUTPUT_ZIP_FILE = "Folder.zip";
private static final String SOURCE_FOLDER = "D:\\Reports"; // SourceFolder path
public ZipUtils() {
fileList = new ArrayList < String > ();
}
public static void main(String[] args) {
ZipUtils appZip = new ZipUtils();
appZip.generateFileList(new File(SOURCE_FOLDER));
appZip.zipIt(OUTPUT_ZIP_FILE);
}
public void zipIt(String zipFile) {
byte[] buffer = new byte[1024];
String source = new File(SOURCE_FOLDER).getName();
FileOutputStream fos = null;
ZipOutputStream zos = null;
try {
fos = new FileOutputStream(zipFile);
zos = new ZipOutputStream(fos);
System.out.println("Output to Zip : " + zipFile);
FileInputStream in = null;
for (String file: this.fileList) {
System.out.println("File Added : " + file);
ZipEntry ze = new ZipEntry(source + File.separator + file);
zos.putNextEntry(ze);
try {
in = new FileInputStream(SOURCE_FOLDER + File.separator + file);
int len;
while ((len = in .read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
} finally {
in.close();
}
}
zos.closeEntry();
System.out.println("Folder successfully compressed");
} catch (IOException ex) {
ex.printStackTrace();
} finally {
try {
zos.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
public void generateFileList(File node) {
// add file only
if (node.isFile()) {
fileList.add(generateZipEntry(node.toString()));
}
if (node.isDirectory()) {
String[] subNote = node.list();
for (String filename: subNote) {
generateFileList(new File(node, filename));
}
}
}
private String generateZipEntry(String file) {
return file.substring(SOURCE_FOLDER.length() + 1, file.length());
}
}
Refer mkyong..I changed the code for the requirement of current question
Here's a pretty terse Java 7+ solution which relies purely on vanilla JDK classes, no third party libraries required:
public static void pack(final Path folder, final Path zipFilePath) throws IOException {
try (
FileOutputStream fos = new FileOutputStream(zipFilePath.toFile());
ZipOutputStream zos = new ZipOutputStream(fos)
) {
Files.walkFileTree(folder, new SimpleFileVisitor<Path>() {
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
zos.putNextEntry(new ZipEntry(folder.relativize(file).toString()));
Files.copy(file, zos);
zos.closeEntry();
return FileVisitResult.CONTINUE;
}
public FileVisitResult preVisitDirectory(Path dir, BasicFileAttributes attrs) throws IOException {
zos.putNextEntry(new ZipEntry(folder.relativize(dir).toString() + "/"));
zos.closeEntry();
return FileVisitResult.CONTINUE;
}
});
}
}
It copies all files in folder, including empty directories, and creates a zip archive at zipFilePath.
Java 7+, commons.io
public final class ZipUtils {
public static void zipFolder(final File folder, final File zipFile) throws IOException {
zipFolder(folder, new FileOutputStream(zipFile));
}
public static void zipFolder(final File folder, final OutputStream outputStream) throws IOException {
try (ZipOutputStream zipOutputStream = new ZipOutputStream(outputStream)) {
processFolder(folder, zipOutputStream, folder.getPath().length() + 1);
}
}
private static void processFolder(final File folder, final ZipOutputStream zipOutputStream, final int prefixLength)
throws IOException {
for (final File file : folder.listFiles()) {
if (file.isFile()) {
final ZipEntry zipEntry = new ZipEntry(file.getPath().substring(prefixLength));
zipOutputStream.putNextEntry(zipEntry);
try (FileInputStream inputStream = new FileInputStream(file)) {
IOUtils.copy(inputStream, zipOutputStream);
}
zipOutputStream.closeEntry();
} else if (file.isDirectory()) {
processFolder(file, zipOutputStream, prefixLength);
}
}
}
}
I usually use a helper class I once wrote for this task:
import java.util.zip.*;
import java.io.*;
public class ZipExample {
public static void main(String[] args){
ZipHelper zippy = new ZipHelper();
try {
zippy.zipDir("folderName","test.zip");
} catch(IOException e2) {
System.err.println(e2);
}
}
}
class ZipHelper
{
public void zipDir(String dirName, String nameZipFile) throws IOException {
ZipOutputStream zip = null;
FileOutputStream fW = null;
fW = new FileOutputStream(nameZipFile);
zip = new ZipOutputStream(fW);
addFolderToZip("", dirName, zip);
zip.close();
fW.close();
}
private void addFolderToZip(String path, String srcFolder, ZipOutputStream zip) throws IOException {
File folder = new File(srcFolder);
if (folder.list().length == 0) {
addFileToZip(path , srcFolder, zip, true);
}
else {
for (String fileName : folder.list()) {
if (path.equals("")) {
addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip, false);
}
else {
addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip, false);
}
}
}
}
private void addFileToZip(String path, String srcFile, ZipOutputStream zip, boolean flag) throws IOException {
File folder = new File(srcFile);
if (flag) {
zip.putNextEntry(new ZipEntry(path + "/" +folder.getName() + "/"));
}
else {
if (folder.isDirectory()) {
addFolderToZip(path, srcFile, zip);
}
else {
byte[] buf = new byte[1024];
int len;
FileInputStream in = new FileInputStream(srcFile);
zip.putNextEntry(new ZipEntry(path + "/" + folder.getName()));
while ((len = in.read(buf)) > 0) {
zip.write(buf, 0, len);
}
}
}
}
}
Enhanced Java 8+ example (Forked from Nikita Koksharov's answer)
public static void pack(String sourceDirPath, String zipFilePath) throws IOException {
Path p = Files.createFile(Paths.get(zipFilePath));
Path pp = Paths.get(sourceDirPath);
try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(p));
Stream<Path> paths = Files.walk(pp)) {
paths
.filter(path -> !Files.isDirectory(path))
.forEach(path -> {
ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString());
try {
zs.putNextEntry(zipEntry);
Files.copy(path, zs);
zs.closeEntry();
} catch (IOException e) {
System.err.println(e);
}
});
}
}
Files.walk has been wrapped in try with resources block so that stream can be closed. This resolves blocker issue identified by SonarQube.
Thanks #Matt Harrison for pointing this.
I would use Apache Ant, which has an API to call tasks from Java code rather than from an XML build file.
Project p = new Project();
p.init();
Zip zip = new Zip();
zip.setProject(p);
zip.setDestFile(zipFile); // a java.io.File for the zip you want to create
zip.setBasedir(new File("D:\\reports"));
zip.setIncludes("january/**");
zip.perform();
Here I'm telling it to start from the base directory D:\reports and zip up the january folder and everything inside it. The paths in the resulting zip file will be the same as the original paths relative to D:\reports, so they will include the january prefix.
Using zip4j you can simply do this
ZipFile zipfile = new ZipFile(new File("D:\\reports\\january\\filename.zip"));
zipfile.addFolder(new File("D:\\reports\\january\\"));
It will archive your folder and everything in it.
Use the .extractAll method to get it all out:
zipfile.extractAll("D:\\destination_directory");
Try this:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Zip {
public static void main(String[] a) throws Exception {
zipFolder("D:\\reports\\january", "D:\\reports\\january.zip");
}
static public void zipFolder(String srcFolder, String destZipFile) throws Exception {
ZipOutputStream zip = null;
FileOutputStream fileWriter = null;
fileWriter = new FileOutputStream(destZipFile);
zip = new ZipOutputStream(fileWriter);
addFolderToZip("", srcFolder, zip);
zip.flush();
zip.close();
}
static private void addFileToZip(String path, String srcFile, ZipOutputStream zip)
throws Exception {
File folder = new File(srcFile);
if (folder.isDirectory()) {
addFolderToZip(path, srcFile, zip);
} else {
byte[] buf = new byte[1024];
int len;
FileInputStream in = new FileInputStream(srcFile);
zip.putNextEntry(new ZipEntry(path + "/" + folder.getName()));
while ((len = in.read(buf)) > 0) {
zip.write(buf, 0, len);
}
}
}
static private void addFolderToZip(String path, String srcFolder, ZipOutputStream zip)
throws Exception {
File folder = new File(srcFolder);
for (String fileName : folder.list()) {
if (path.equals("")) {
addFileToZip(folder.getName(), srcFolder + "/" + fileName, zip);
} else {
addFileToZip(path + "/" + folder.getName(), srcFolder + "/" + fileName, zip);
}
}
}
}
Java 6 +
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Zip {
private static final FileFilter FOLDER_FILTER = new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.isDirectory();
}
};
private static final FileFilter FILE_FILTER = new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.isFile();
}
};
private static void compress(File file, ZipOutputStream outputStream, String path) throws IOException {
if (file.isDirectory()) {
File[] subFiles = file.listFiles(FILE_FILTER);
if (subFiles != null) {
for (File subFile : subFiles) {
compress(subFile, outputStream, new File(path, subFile.getName()).getAbsolutePath());
}
}
File[] subDirs = file.listFiles(FOLDER_FILTER);
if (subDirs != null) {
for (File subDir : subDirs) {
compress(subDir, outputStream, new File(path, subDir.getName()).getAbsolutePath());
}
}
} else if (file.exists()) {
outputStream.putNextEntry(new ZipEntry(path));
FileInputStream inputStream = new FileInputStream(file);
byte[] buffer = new byte[1024];
int len;
while ((len = inputStream.read(buffer)) >= 0) {
outputStream.write(buffer, 0, len);
}
outputStream.closeEntry();
}
}
public static void compress(String dirPath, String zipFilePath) throws IOException {
File file = new File(dirPath);
final ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(zipFilePath));
compress(file, outputStream, "/");
outputStream.close();
}
}
I found this solution worked perfectly fine for me. Doesn't require any third party apis
'test' is actually a folder will lots of file inside.
String folderPath= "C:\Users\Desktop\test";
String zipPath = "C:\Users\Desktop\test1.zip";
private boolean zipDirectory(String folderPath, String zipPath) throws IOException{
byte[] buffer = new byte[1024];
FileInputStream fis = null;
ZipOutputStream zos = null;
try{
zos = new ZipOutputStream(new FileOutputStream(zipPath));
updateSourceFolder(new File(folderPath));
if (sourceFolder == null) {
zos.close();
return false;
}
generateFileAndFolderList(new File(folderPath));
for (String unzippedFile: fileList) {
System.out.println(sourceFolder + unzippedFile);
ZipEntry entry = new ZipEntry(unzippedFile);
zos.putNextEntry(entry);
if ((unzippedFile.substring(unzippedFile.length()-1)).equals(File.separator))
continue;
try{
fis = new FileInputStream(sourceFolder + unzippedFile);
int len=0;
while ((len = fis.read(buffer))>0) {
zos.write(buffer,0,len);
}
} catch(IOException e) {
return false;
} finally {
if (fis != null)
fis.close();
}
}
zos.closeEntry();
} catch(IOException e) {
return false;
} finally {
zos.close();
fileList = null;
sourceFolder = null;
}
return true;
}
private void generateFileAndFolderList(File node) {
if (node.isFile()) {
fileList.add(generateZipEntry(node.getAbsoluteFile().toString()));
}
if (node.isDirectory()) {
String dir = node.getAbsoluteFile().toString();
fileList.add(dir.substring(sourceFolder.length(), dir.length()) + File.separator);
String[] subNode = node.list();
for (String fileOrFolderName : subNode) {
generateFileAndFolderList(new File(node, fileOrFolderName));
}
}
}
private void updateSourceFolder(File node) {
if (node.isFile() || node.isDirectory()) {
String sf = node.getAbsoluteFile().toString();
sourceFolder = sf.substring(0, (sf.lastIndexOf("/") > 0 ? sf.lastIndexOf("/") : sf.lastIndexOf("\\")));
sourceFolder += File.separator;
} else
sourceFolder = null;
}
private String generateZipEntry(String file) {
return file.substring(sourceFolder.length(), file.length());
}
This method zips a folder and adds all of the child files & folders (including empty folders) into the zip file.
void zipFolder(Path sourceDir, Path targetFile) throws IOException {
ZipDirectoryVisitor zipVisitor = new ZipDirectoryVisitor(sourceDir);
Files.walkFileTree(sourceDir, zipVisitor);
FileOutputStream fos = new FileOutputStream(targetFile.toString());
ZipOutputStream zos = new ZipOutputStream(fos);
byte[] buffer = new byte[1024];
for (ZipEntry entry : zipVisitor.getZipEntries()) {
zos.putNextEntry(entry);
Path curFile = Paths.get(sourceDir.getParent().toString(), entry.toString());
if (!curFile.toFile().isDirectory()) {
FileInputStream in = new FileInputStream(Paths.get(sourceDir.getParent().toString(), entry.toString()).toString());
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
in.close();
}
zos.closeEntry();
}
zos.close();
}
And here is the ZipDirectoryVisitor implementation:
class ZipDirectoryVisitor extends SimpleFileVisitor<Path> {
private Path dirToZip;
private List<ZipEntry> zipEntries; // files and folders inside source folder as zip entries
public ZipDirectoryVisitor(Path dirToZip) throws IOException {
this.dirToZip = dirToZip;
zipEntries = new ArrayList<>();
}
#Override
public FileVisitResult visitFile(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
// According to zip standard backslashes
// should not be used in zip entries
String zipFile = dirToZip.getParent().relativize(path).toString().replace("\\", "/");
ZipEntry entry = new ZipEntry(zipFile);
zipEntries.add(entry);
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult preVisitDirectory(Path path, BasicFileAttributes basicFileAttributes) throws IOException {
String zipDir = dirToZip.getParent().relativize(path).toString().replace("\\", "/");
// Zip directory entries should end with a forward slash
ZipEntry entry = new ZipEntry(zipDir + "/");
zipEntries.add(entry);
return FileVisitResult.CONTINUE;
}
#Override
public FileVisitResult visitFileFailed(Path path, IOException e) throws IOException {
System.err.format("Could not visit file %s while creating a file list from file tree", path);
return FileVisitResult.TERMINATE;
}
public List<ZipEntry> getZipEntries() {
return zipEntries;
}
}
I have modified the above solutions and replaced Files.walk with Files.list. This also assumes the directory you are zipping only contains file and not any sub directories.
private void zipDirectory(Path dirPath) throws IOException {
String zipFilePathStr = dirPath.toString() + ".zip";
Path zipFilePath = Files.createFile(Paths.get(zipFilePathStr));
try (ZipOutputStream zs = new ZipOutputStream(Files.newOutputStream(zipFilePath))) {
Files.list(dirPath)
.filter(filePath-> !Files.isDirectory(filePath))
.forEach(filePath-> {
ZipEntry zipEntry = new ZipEntry(dirPath.relativize(filePath).toString());
try {
zs.putNextEntry(zipEntry);
Files.copy(filePath, zs);
zs.closeEntry();
}
catch (IOException e) {
System.err.println(e);
}
});
}
}
Improving #Nikita Koksharov's code had problems packing empty directories.
private void zipDirectory(OutputStream outputStream, Path directoryPath) throws IOException {
try (ZipOutputStream zs = new ZipOutputStream(outputStream)) {
Path pp = directoryPath;
Files.walk(pp)
.forEach(path -> {
try {
if (Files.isDirectory(path)) {
zs.putNextEntry(new ZipEntry(pp.relativize(path).toString() + "/"));
} else {
ZipEntry zipEntry = new ZipEntry(pp.relativize(path).toString());
zs.putNextEntry(zipEntry);
Files.copy(path, zs);
zs.closeEntry();
}
} catch (IOException e) {
System.err.println(e);
}
});
}
}
Test usage
FileOutputStream zipOutput = new FileOutputStream("path_to_file.zip");
Path pathOutput = Path.of("path_directory_fid");
zipDirectory(outputStream, pathOutput);
try this zip("C:\testFolder", "D:\testZip.zip")
public void zip( String sourcDirPath, String zipPath) throws IOException {
Path zipFile = Files.createFile(Paths.get(zipPath));
Path sourceDirPath = Paths.get(sourcDirPath);
try (ZipOutputStream zipOutputStream = new ZipOutputStream(Files.newOutputStream(zipFile));
Stream<Path> paths = Files.walk(sourceDirPath)) {
paths
.filter(path -> !Files.isDirectory(path))
.forEach(path -> {
ZipEntry zipEntry = new ZipEntry(sourceDirPath.relativize(path).toString());
try {
zipOutputStream.putNextEntry(zipEntry);
Files.copy(path, zipOutputStream);
zipOutputStream.closeEntry();
} catch (IOException e) {
System.err.println(e);
}
});
}
System.out.println("Zip is created at : "+zipFile);
}
Im making a backup program, and I want everything that i have the program backing up displayed on a JTextArea. well, it works, but only after the program is finished with the backup. How do i fix this? The code i have running this is here:
backup method
public void startBackup() throws Exception {
// txtarea is the JTextArea
Panel.txtArea.append("Starting Backup...\n");
for (int i = 0; i < al.size(); i++) {
//al is an ArrayList that holds all of the backup assignments selected
// from the JFileChooser
File file = new File((String) al.get(i));
File directory = new File(dir);
CopyFolder.copyFolder(file, directory);
}
}
Copy Folder class:
public class CopyFolder {
public static void copyFolder(File src, File dest) throws IOException {
if (src.isDirectory()) {
// if directory not exists, create it
if (!dest.exists()) {
dest.mkdir();
Panel.txtArea.append("Folder " + src.getName()
+ " was created\n");
}
// list all the directory contents
String files[] = src.list();
for (String file : files) {
// construct the src and dest file structure
File srcFile = new File(src, file);
File destFile = new File(dest, file);
// recursive copy
copyFolder(srcFile, destFile);
}
} else {
try {
CopyFile.copyFile(src, dest);
} catch (Exception e) {
}
}
}
}
CopyFile class
public class CopyFile {
public static void copyFile(File src, File dest) throws Exception {
// if file, then copy it
// Use bytes stream to support all file types
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
// copy the file content in bytes
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
in.close();
out.close();
// System.out.println("File copied from " + src + " to " + dest);
Panel.txtArea.append("File copied " + src.getName() + "\n");
}
}
Thanks for the help in advance, and let me know of any assistance i can give. I did a google search on this, and it does seem to be a big problem, but i just cant think of how to fix it. Oh, and please dont downvote this just because it doesnt apply to you, its very aggravating. Thanks in advance again!
EDIT:
This is what i got:
public class test extends SwingWorker<Void, String> {
String txt;
JTextArea txtArea = null;
public test(JTextArea txtArea, String str) {
txt = str;
this.txtArea = txtArea;
}
protected Void doInBackground() throws Exception {
return null;
}
protected void process(String str) {
txtArea.append(str);
}
protected void getString() {
publish(txt);
}
}
The main problem you're having is you're trying to perform blocking actions in the Event Dispatching Thread. This will prevent the UI from been updated as repaint requests are not reaching the repaint manager until AFTER you've finished.
To over come this, you're going to need to off load the blocking work (ie the back up process) to a separate thread.
For this I suggest you have a read through the Concurrency in Swing Trail which will provide you with some useful strategies to solve your particular problem. In particular, you'll probably benifit from using a SwingWorker
Take a close look at doInBackground and the process methods
UPDATED with Example
Okay, so this is a REALLY simple example. This basically walks you C:\ drive to 3 directories deep and dumps the content to the supplied JTextArea
public class BackgroundWorker extends SwingWorker<Object, File> {
private JTextArea textArea;
public BackgroundWorker(JTextArea textArea) {
this.textArea = textArea;
}
#Override
protected Object doInBackground() throws Exception {
list(new File("C:\\"), 0);
return null;
}
#Override
protected void process(List<File> chunks) {
for (File file : chunks) {
textArea.append(file.getPath() + "\n");
}
textArea.setCaretPosition(textArea.getText().length() - 1);
}
protected void list(File path, int level) {
if (level < 4) {
System.out.println(level + " - Listing " + path);
File[] files = path.listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.isFile();
}
});
publish(path);
for (File file : files) {
System.out.println(file);
publish(file);
}
files = path.listFiles(new FileFilter() {
#Override
public boolean accept(File pathname) {
return pathname.isDirectory() && !pathname.isHidden();
}
});
for (File folder : files) {
list(folder, level + 1);
}
}
}
}
You would simply call new BackgroundWorker(textField).execute() and walk away :D
UPDATED with explicit example
public class BackgroundWorker extends SwingWorker<Object, String> {
private JTextArea textArea;
private File sourceDir;
private File destDir;
public BackgroundWorker(JTextArea textArea, File sourceDir, File destDir) {
this.textArea = textArea;
this.sourceDir = sourceDir;
this.destDir = destDirl
}
#Override
protected Object doInBackground() throws Exception {
if (sourceDir.isDirectory()) {
// if directory not exists, create it
if (!destDir.exists()) {
destDir.mkdir();
publish("Folder " + sourceDir.getName() + " was created");
}
// list all the directory contents
String files[] = sourceDir.list();
for (String file : files) {
// construct the src and dest file structure
File srcFile = new File(sourceDir, file);
File destFile = new File(destDir, file);
// recursive copy
copyFolder(srcFile, destFile);
}
} else {
try {
copyFile(sourceDir, destDir);
} catch (Exception e) {
}
}
return null;
}
public void copyFolder(File src, File dest) throws IOException {
if (src.isDirectory()) {
// if directory not exists, create it
if (!dest.exists()) {
publish("Folder " + src.getName() + " was created");
}
// list all the directory contents
String files[] = src.list();
for (String file : files) {
// construct the src and dest file structure
File srcFile = new File(src, file);
File destFile = new File(dest, file);
// recursive copy
copyFolder(srcFile, destFile);
}
} else {
try {
copyFile(src, dest);
} catch (Exception e) {
}
}
}
public void copyFile(File src, File dest) throws Exception {
// if file, then copy it
// Use bytes stream to support all file types
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
// copy the file content in bytes
while ((length = in.read(buffer)) > 0) {
out.write(buffer, 0, length);
}
in.close();
out.close();
publish("File copied " + src.getName());
}
#Override
protected void process(List<String> chunks) {
for (String msg : chunks) {
textArea.append(msg + "\n");
}
textArea.setCaretPosition(textArea.getText().length() - 1);
}
}
Now to run...
new BackgroundWorker(textArea, sourceDir, destDir).execute();