I have used below function to zip multiple images from my folder, mainViewModel.getImagesList() will return array of images path which i want to added in zip folder
public void compressImagesToZip() throws IOException {
BufferedInputStream origin = null;
String opd = Environment.getExternalStorageDirectory() + "/" + getApplication().getApplicationContext().getResources().getString(R.string.imageFolder) + "/GroTrack.zip";
Log.e("====>>", opd);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(opd)));
try {
byte data[] = new byte[2048];
for (int i = 0; i < mainViewModel.getImagesList().size(); i++) {
FileInputStream fi = new FileInputStream(mainViewModel.getImagesList().get(i));
origin = new BufferedInputStream(fi, 2048);
try {
ZipEntry entry = new ZipEntry(mainViewModel.getImagesList().get(i).substring(mainViewModel.getImagesList().get(i).lastIndexOf("/") + 1));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, 2048)) != -1) {
out.write(data, 0, count);
}
} finally {
origin.close();
}
}
} finally {
out.close();
}
}
Please refere this images, before zip and after zip image sizes were different
before
after
I use this code to ZIP folders including inner folders :
public boolean zipFileAtPath(String sourcePath, String toLocation) {
// ArrayList<String> contentList = new ArrayList<String>();
final int BUFFER = 2048;
File sourceFile = new File(sourcePath);
try {
BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(toLocation);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
dest));
if (sourceFile.isDirectory()) {
zipSubFolder(out, sourceFile, sourceFile.getParent().length());
} else {
byte data[] = new byte[BUFFER];
FileInputStream fi = new FileInputStream(sourcePath);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(getLastPathComponent(sourcePath));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
}
out.close();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
private void zipSubFolder(ZipOutputStream out, File folder,
int basePathLength) throws IOException {
final int BUFFER = 2048;
File[] fileList = folder.listFiles();
BufferedInputStream origin = null;
for (File file : fileList) {
if (file.isDirectory()) {
zipSubFolder(out, file, basePathLength);
} else {
byte data[] = new byte[BUFFER];
String unmodifiedFilePath = file.getPath();
String relativePath = unmodifiedFilePath
.substring(basePathLength);
Log.i("ZIP SUBFOLDER", "Relative Path : " + relativePath);
FileInputStream fi = new FileInputStream(unmodifiedFilePath);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(relativePath);
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
}
}
public String getLastPathComponent(String filePath) {
String[] segments = filePath.split("/");
String lastPathComponent = segments[segments.length - 1];
return lastPathComponent;
}
It works fine when folder looks like :
Folder
txt file
jpg file
txt file
It also works fine when folder looks like :
Folder
txt file
Folder
txt file
txt file
However in this case :
Folder
txt file
Folder
txt file
jpg file
txt file
it starts endless loop, when ZIP file continuously increases.
I noted, that it happens because this loop :
private void zipSubFolder(ZipOutputStream out, File folder,
int basePathLength) throws IOException {
.....
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
....
}
doesn't stop in the case, described above.
Any ideas why this can happen ? Thanks )
Here is the solution.
I save ZIP file inside the same folder, that is zipped. So it starts to zip the ZIP file itself, saving new ZIP file inside again and again and again.
Not sure, if it's clear, but anyway, pay attention where do you save ZIP file.
Could someone help me, in my application I would like to export my images from gallery to .zip, but I have no idea what I need to do that. I will be grateful for any tips
This is some basic zip code. Essentially create a string array containing all the image file paths you want to include in the zip and another string for the destination path of your zip file. Pass these on to the method.
public static void zip(String[] files, String zipFile) throws IOException {
BufferedInputStream origin = null;
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
try {
byte data[] = new byte[BUFFER_SIZE];
for (int i = 0; i < files.length; i++) {
FileInputStream fi = new FileInputStream(files[i]);
origin = new BufferedInputStream(fi, BUFFER_SIZE);
try {
ZipEntry entry = new ZipEntry(files[i].substring(files[i].lastIndexOf("/") + 1));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) {
out.write(data, 0, count);
}
}
finally {
origin.close();
}
}
}
finally {
out.close();
}
}
Or alternatively, you can use the Zip4j library.
Happy coding! :D
Use "
Easy Unrar, Unzip & Zip
"
Find the directory of the gallery, compress it
EDITED
Try this:
public static void compress(String[] folder, String compFile) throws IOException {
BufferedInputStream origin = null;
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(compFile)));
try {
byte data[] = new byte[BUFFER_SIZE];
for (int i = 0; i < folder.length; i++) {
FileInputStream fi = new FileInputStream(folder[i]);
origin = new BufferedInputStream(fi, BUFFER_SIZE);
try {
ZipEntry entry = new ZipEntry(folder[i].substring(folder[i].lastIndexOf("/") + 1));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) {
out.write(data, 0, count);
}
}
finally {
origin.close();
}
}
}
finally {
out.close();
}
}
Hi in my app when i click zip button i need to zip image file and and when i click unzip button i need to unzip file,i tried using below code to zip image but my problem is when i click zip button zip file is creating,but after that in system using winzip software i try to open file but its not opening its showing "it does not appear to a valid archive valid file" where i did mistake can u let me how to zip and unzip images
public class MainActivity extends Activity {
/** Called when the activity is first created. */
Button zip,unzip;
String []s=new String[2];
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
zip=(Button)findViewById(R.id.button1);
zip.setOnClickListener(new OnClickListener() {
public void onClick(View arg0) {
// TODO Auto-generated method stub
s[0]="/sdcard/saved_images/Main.png";
//s[1]="/sdcard/Physics_Lab/Stefans_Law/stefan_law.txt"; // path of the second file
Compress c =new Compress(s,"/sdcard/saved_images/stefen.zip");
c.zip();
}
});
}
}
public class Compress {
private static final int BUFFER = 80000;
private String[] _files;
private String _zipFile;
public Compress(String[] files, String zipFile) {
_files = files;
_zipFile = zipFile;
}
public void zip() {
try {
BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(_zipFile);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(dest));
byte data[] = new byte[BUFFER];
for(int i=0; i < _files.length; i++) {
Log.d("add:",_files[i]);
Log.v("Compress", "Adding: " + _files[i]);
FileInputStream fi = new FileInputStream(_files[i]);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(_files[i].substring(_files[i].lastIndexOf("/") + 1));
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
out.close();
} catch(Exception e) {
e.printStackTrace();
}
}
}
You can check out these 2 tutorials to zip and unzip the file
Android Zip file
Android Unzip file
You can use ZipOutputStream in Java
See API Document Here
You can create the zip file by follow function
OutputStream os = ...
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(os));
try {
for (int i = 0; i < fileCount; ++i) {
String filename = ...
byte[] bytes = ...
ZipEntry entry = new ZipEntry(filename);
zos.putNextEntry(entry);
zos.write(bytes);
zos.closeEntry();
}
} finally {
zos.close();
}
For Open a zip file, you can use ZipInputStream
Api Document here
InputStream is = ...
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(is));
try {
ZipEntry ze;
while ((ze = zis.getNextEntry()) != null) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
int count;
while ((count = zis.read(buffer)) != -1) {
baos.write(buffer, 0, count);
}
String filename = ze.getName();
byte[] bytes = baos.toByteArray();
// do something with 'filename' and 'bytes'...
}
} finally {
zis.close();
}
I need to zip up a "project" folder to allow users to share projects via email. I found a class for zipping up multiple files into one zip, but I need to keep the folder structure in my zip. Is there any way to achieve this on android? Thanks in advance.
This code should do the trick.
Note: you must add file write permissions to your app by adding the WRITE_EXTERNAL_STORAGE permission to your manifest.xml file.
/*
*
* Zips a file at a location and places the resulting zip file at the toLocation
* Example: zipFileAtPath("downloads/myfolder", "downloads/myFolder.zip");
*/
public boolean zipFileAtPath(String sourcePath, String toLocation) {
final int BUFFER = 2048;
File sourceFile = new File(sourcePath);
try {
BufferedInputStream origin = null;
FileOutputStream dest = new FileOutputStream(toLocation);
ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream(
dest));
if (sourceFile.isDirectory()) {
zipSubFolder(out, sourceFile, sourceFile.getParent().length());
} else {
byte data[] = new byte[BUFFER];
FileInputStream fi = new FileInputStream(sourcePath);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(getLastPathComponent(sourcePath));
entry.setTime(sourceFile.lastModified()); // to keep modification time after unzipping
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
}
out.close();
} catch (Exception e) {
e.printStackTrace();
return false;
}
return true;
}
/*
*
* Zips a subfolder
*
*/
private void zipSubFolder(ZipOutputStream out, File folder,
int basePathLength) throws IOException {
final int BUFFER = 2048;
File[] fileList = folder.listFiles();
BufferedInputStream origin = null;
for (File file : fileList) {
if (file.isDirectory()) {
zipSubFolder(out, file, basePathLength);
} else {
byte data[] = new byte[BUFFER];
String unmodifiedFilePath = file.getPath();
String relativePath = unmodifiedFilePath
.substring(basePathLength);
FileInputStream fi = new FileInputStream(unmodifiedFilePath);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(relativePath);
entry.setTime(file.lastModified()); // to keep modification time after unzipping
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
}
}
}
/*
* gets the last path component
*
* Example: getLastPathComponent("downloads/example/fileToZip");
* Result: "fileToZip"
*/
public String getLastPathComponent(String filePath) {
String[] segments = filePath.split("/");
if (segments.length == 0)
return "";
String lastPathComponent = segments[segments.length - 1];
return lastPathComponent;
}
this is how I do it:
private static void zipFolder(String inputFolderPath, String outZipPath) {
try {
FileOutputStream fos = new FileOutputStream(outZipPath);
ZipOutputStream zos = new ZipOutputStream(fos);
File srcFile = new File(inputFolderPath);
File[] files = srcFile.listFiles();
Log.d("", "Zip directory: " + srcFile.getName());
for (int i = 0; i < files.length; i++) {
Log.d("", "Adding file: " + files[i].getName());
byte[] buffer = new byte[1024];
FileInputStream fis = new FileInputStream(files[i]);
zos.putNextEntry(new ZipEntry(files[i].getName()));
int length;
while ((length = fis.read(buffer)) > 0) {
zos.write(buffer, 0, length);
}
zos.closeEntry();
fis.close();
}
zos.close();
} catch (IOException ioe) {
Log.e("", ioe.getMessage());
}
}
I have reworked the code from HailZeon to work properly under windows. Zip Entries must be closed before new ones are started and a starting "/" at entry names like "/file.txt" makes also problems
/**
* Zips a Folder to "[Folder].zip"
* #param toZipFolder Folder to be zipped
* #return the resulting ZipFile
*/
public static File zipFolder(File toZipFolder) {
File ZipFile = new File(toZipFolder.getParent(), format("%s.zip", toZipFolder.getName()));
try {
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(ZipFile));
zipSubFolder(out, toZipFolder, toZipFolder.getPath().length());
out.close();
return ZipFile;
} catch (Exception ex) {
ex.printStackTrace();
return null;
}
}
/**
* Main zip Function
* #param out Target ZipStream
* #param folder Folder to be zipped
* #param basePathLength Length of original Folder Path (for recursion)
*/
private static void zipSubFolder(ZipOutputStream out, File folder, int basePathLength) throws IOException {
final int BUFFER = 2048;
File[] fileList = folder.listFiles();
BufferedInputStream origin = null;
for (File file : fileList) {
if (file.isDirectory()) {
zipSubFolder(out, file, basePathLength);
} else {
byte data[] = new byte[BUFFER];
String unmodifiedFilePath = file.getPath();
String relativePath = unmodifiedFilePath.substring(basePathLength + 1);
FileInputStream fi = new FileInputStream(unmodifiedFilePath);
origin = new BufferedInputStream(fi, BUFFER);
ZipEntry entry = new ZipEntry(relativePath);
entry.setTime(file.lastModified()); // to keep modification time after unzipping
out.putNextEntry(entry);
int count;
while ((count = origin.read(data, 0, BUFFER)) != -1) {
out.write(data, 0, count);
}
origin.close();
out.closeEntry();
}
}
}
Use the zip4j library from this location. Import the jar file to your "app/libs/" folder. And use the following code to zip your directories/files...
try {
File input = new File("path/to/your/input/fileOrFolder");
String destinationPath = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "zippedItem.zip";
ZipParameters parameters = new ZipParameters();
parameters.setCompressionMethod(Zip4jConstants.COMP_STORE);
parameters.setCompressionLevel(Zip4jConstants.DEFLATE_LEVEL_NORMAL);
File output = new File(destinationPath);
ZipFile zipFile = new ZipFile(output);
// .addFolder or .addFile depending on your input
if (sourceFile.isDirectory())
zipFile.addFolder(input, parameters);
else
zipFile.addFile(input, parameters);
// Your input file/directory has been zipped at this point and you
// can access it as a normal file using the following line of code
File zippedFile = zipFile.getFile();
} catch (ZipException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
If you use a java.util.zip object then you can write a script that does not modify the directory structure.
public static boolean zip(File sourceFile, File zipFile) {
List<File> fileList = getSubFiles(sourceFile, true);
ZipOutputStream zipOutputStream = null;
try {
zipOutputStream = new ZipOutputStream(new FileOutputStream(zipFile));
int bufferSize = 1024;
byte[] buf = new byte[bufferSize];
ZipEntry zipEntry;
for(int i = 0; i < fileList.size(); i++) {
File file = fileList.get(i);
zipEntry = new ZipEntry(sourceFile.toURI().relativize(file.toURI()).getPath());
zipOutputStream.putNextEntry(zipEntry);
if (!file.isDirectory()) {
InputStream inputStream = new BufferedInputStream(new FileInputStream(file));
int readLength;
while ((readLength = inputStream.read(buf, 0, bufferSize)) != -1) {
zipOutputStream.write(buf, 0, readLength);
}
}
}
} catch (Exception e) {
e.printStackTrace();
return false;
} finally {
IoUtils.closeOS(zipOutputStream);
}
return true;
}
public static List<File> getSubFiles(File baseDir, boolean isContainFolder) {
List<File> fileList = new ArrayList<>();
File[] tmpList = baseDir.listFiles();
for (File file : tmpList) {
if (file.isFile()) {
fileList.add(file);
}
if (file.isDirectory()) {
if (isContainFolder) {
fileList.add(file); //key code
}
fileList.addAll(getSubFiles(file));
}
}
return fileList;
}
Just converting #HailZeon's answer to Kotlin:
import java.io.BufferedInputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.util.zip.ZipEntry
import java.util.zip.ZipOutputStream
import java.util.zip.ZipException
private const val BUFFER = 2048
/**
* Compresses a file into a zip file
* #author Arnau Mora
* #since 20210318
* #param file The source file
* #param target The target file
*
* #throws NullPointerException If the entry name is null
* #throws IllegalArgumentException If the entry name is longer than 0xFFFF byte
* #throws SecurityException If a security manager exists and its SecurityManager.checkRead(String)
* method denies read access to the file
* #throws ZipException If a ZIP format error has occurred
* #throws IOException If an I/O error has occurre
*/
#Throws(
NullPointerException::class,
IllegalArgumentException::class,
SecurityException::class,
ZipException::class,
IOException::class
)
fun zipFile(file: File, target: File) {
val origin: BufferedInputStream
val dest: FileOutputStream
var zipOutput: ZipOutputStream? = null
try {
dest = target.outputStream()
zipOutput = ZipOutputStream(dest.buffered(BUFFER))
if (file.isDirectory)
zipSubFolder(zipOutput, file, file.parent!!.length)
else {
val data = ByteArray(BUFFER)
val fi = file.inputStream()
origin = fi.buffered(BUFFER)
val entry = ZipEntry(getLastPathComponent(file.path))
entry.time = file.lastModified()
zipOutput.putNextEntry(entry)
var count = origin.read(data, 0, BUFFER)
while (count != -1) {
zipOutput.write(data, 0, count)
count = origin.read(data, 0, BUFFER)
}
}
} finally {
zipOutput?.close()
}
}
private fun zipSubFolder(zipOutput: ZipOutputStream, folder: File, basePathLength: Int) {
val files = folder.listFiles() ?: return
var origin: BufferedInputStream? = null
try {
for (file in files) {
if (file.isDirectory)
zipSubFolder(zipOutput, folder, basePathLength)
else {
val data = ByteArray(BUFFER)
val unmodifiedFilePath = file.path
val relativePath = unmodifiedFilePath.substring(basePathLength)
val fi = FileInputStream(unmodifiedFilePath)
origin = fi.buffered(BUFFER)
val entry = ZipEntry(relativePath)
entry.time = file.lastModified()
zipOutput.putNextEntry(entry)
var count = origin.read(data, 0, BUFFER)
while (count != -1) {
zipOutput.write(data, 0, count)
count = origin.read(data, 0, BUFFER)
}
}
}
} finally {
origin?.close()
}
}
/*
* gets the last path component
*
* Example: getLastPathComponent("downloads/example/fileToZip");
* Result: "fileToZip"
*/
private fun getLastPathComponent(filePath: String): String {
val segments = filePath.split("/").toTypedArray()
return if (segments.isEmpty()) "" else segments[segments.size - 1]
}
If someone comes here trying to find a java8 cleaner refactored version of the #HailZeon code. Here it is:
private static final int BUFFER_SIZE = 2048;
public File zip(File source, String zipFileName) throws IOException {
File zipFile = null;
if(source != null) {
File zipFileDestination = new File(getCacheDir(), zipFileName);
if (zipFileDestination.exists()) {
zipFileDestination.delete();
}
zipFile = zip(source, zipFileDestination);
}
return zipFile;
}
public File zip(File source, File zipFile) throws IOException {
int relativeStartingPathIndex = zipFile.getAbsolutePath().lastIndexOf("/") + 1;
if (source != null && zipFile != null) {
try (ZipOutputStream out = new ZipOutputStream(new BufferedOutputStream( new FileOutputStream(zipFile)))) {
if (source.isDirectory()) {
zipSubDir(out, source, relativeStartingPathIndex);
} else {
try (BufferedInputStream origin = new BufferedInputStream(new FileInputStream(source))) {
zipEntryFile(origin, out, source, relativeStartingPathIndex);
}
}
}
}
return zipFile;
}
private void zipSubDir(ZipOutputStream out, File dir, int relativeStartingPathIndex) throws IOException {
File[] files = dir.listFiles();
if (files != null) {
for(File file : files) {
if(file.isDirectory()) {
zipSubDir(out, file, relativeStartingPathIndex);
} else {
try (BufferedInputStream origin = new BufferedInputStream(new FileInputStream(file))) {
zipEntryFile(origin, out, file, relativeStartingPathIndex);
}
}
}
}
}
private void zipEntryFile(BufferedInputStream origin, ZipOutputStream out, File file, int relativeStartingPathIndex) throws IOException {
String relativePath = file.getAbsolutePath().substring(relativeStartingPathIndex);
ZipEntry entry = new ZipEntry(relativePath);
entry.setTime(file.lastModified()); // to keep modification time after unzipping
out.putNextEntry(entry);
byte[] data = new byte[BUFFER_SIZE];
int count;
while ((count = origin.read(data, 0, BUFFER_SIZE)) != -1) {
out.write(data, 0, count);
}
}