I need to create some compressed(zip) files and I am using the code below:
public void zipFile(String filePath, String toPath) {
ZipOutputStream outputStream = new ZipOutputStream(new FileOutputStream(toPath));
zip(outputStream, filePath, null);
outputStream.close();
return true;
}
private static void zip(ZipOutputStream os, String filePath, String name) throws java.io.IOException {
File file = new File(filePath);
ZipEntry entry = new ZipEntry((name != null ? name + separator : "") + file.getName() + (file.isDirectory() ? separator : ""));
os.putNextEntry(entry);
if (file.isFile()) {
InputStream is = new FileInputStream(file);
int size = is.available();
byte[] buff = new byte[size];
int len = is.read(buff);
os.write(buff, 0, len);
return;
}
File[] fileArr = file.listFiles();
assert fileArr != null;
for (File subFile : fileArr) {
zip(os, subFile.getAbsolutePath(), entry.getName());
}
}
The code is working well but the problem is:
How to compress(zip) multiple files or folders into a single path?
I mean, let's assume, I have some files below :
-file1
-file2
-file3
and want to zip in a path .../project.zip
But I can't do this with my code.
How can I do it??
Related
I need to zip a 30MB file into different zip files which have a limit of 5MB per zip file.
My work will stop to zip after the size is larger than the limit now. I referenced and tried some examples but made me feel confused.
Please give me suggestions. Thank you.
public static void zipDirectory(File dir, File zipFile, boolean contentOnly)
throws IOException {
synchronized (syncObj) {
FileOutputStream fout = new FileOutputStream(zipFile);
ZipOutputStream zout = new ZipOutputStream(fout);
if (contentOnly)
zipSubDirectory("", dir, zout);
else
zipSubDirectory(dir.getName() + "/", dir, zout);
zout.close();
}
}
private static void zipSubDirectory(String basePath, File dir,
ZipOutputStream zout) throws IOException {
synchronized (syncObj) {
byte[] buffer = new byte[4096];
final long MAX_ZIP_SIZE = 5000000;
long currentSize = 0;
int zipSplitCount = 0;
ZipEntry zipEntry;
FileInputStream entryFile;
File[] files = dir.listFiles();
for (File file : files) {
zipEntry = new ZipEntry(basePath + file.getName());
if (file.isDirectory()) {
String path = basePath + file.getName() + "/";
zout.putNextEntry(new ZipEntry(path));
zipSubDirectory(path, file, zout);
zout.closeEntry();
} else {
if (currentSize >= MAX_ZIP_SIZE) {
zipSplitCount++;
zout.close();
zout = new ZipOutputStream(new FileOutputStream(file.getName().replace(".zip", ".zip." + zipSplitCount)));
currentSize = 0;
}
zout.putNextEntry(zipEntry);
FileInputStream fin = new FileInputStream(file);
int length;
while ((length = fin.read(buffer)) > 0) {
zout.write(buffer, 0, length);
}
zout.closeEntry();
fin.close();
}
currentSize += zipEntry.getCompressedSize();
}
}
}
I have this updater class that updates my program by unzipping a zip file. It works good except when I add in a folder for it to extract.. I have included the 3 methods that I use to accomplish this but the problem must lie in the unzip() method.
Once it prints Extracting: New folder/TEST2.txt it makes the error posted below. I have tried making the folder without spaces and it throws the same error. The contests of the zip file are just 2 text files and a folder.
Structure of zip:
New Folder >Test2.txt
Test1.txt
Errors:
java.io.IOException: The system cannot find the path specified at
java.io.WinNTFileSystem.createFileExclusively(Native Method) at
java.io.File.createNewFile(Unknown Source) at
update.Main_Gui.unzip(Main_Gui.java:244) at
update.Main_Gui.access$3(Main_Gui.java:230) at
update.Main_Gui$3.run(Main_Gui.java:108) at
java.lang.Thread.run(Unknown Source)
Code:
private void copyFiles(File f, String dir) throws IOException {
File[] files = f.listFiles();
for (File ff : files) {
if (ff.isDirectory()) {
new File(dir + "/" + ff.getName()).mkdir();
copyFiles(ff, dir + "/" + ff.getName());
} else {
copy(ff.getAbsolutePath(), dir + "/" + ff.getName());
}
}
}
public void copy(String srFile, String dtFile)
throws FileNotFoundException, IOException {
File f1 = new File(srFile);
File f2 = new File(dtFile);
InputStream in = new FileInputStream(f1);
OutputStream out = new FileOutputStream(f2);
byte[] buf = new byte[1024];
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
in.close();
out.close();
}
private void unzip() throws IOException {
int BUFFER = 2048;
BufferedOutputStream dest = null;
BufferedInputStream is = null;
ZipEntry entry;
ZipFile zipfile = new ZipFile("update.zip");
Enumeration e = zipfile.entries();
(new File(root)).mkdir();
while (e.hasMoreElements()) {
entry = (ZipEntry) e.nextElement();
outText.setText(outText.getText() + "\nExtracting: " + entry);
if (entry.isDirectory())
(new File(root + entry.getName())).mkdir();
else {
(new File(root + entry.getName())).createNewFile();
is = new BufferedInputStream(zipfile.getInputStream(entry));
int count;
byte data[] = new byte[BUFFER];
FileOutputStream fos = new FileOutputStream(root
+ entry.getName());
dest = new BufferedOutputStream(fos, BUFFER);
while ((count = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, count);
}
//zipfile.close();
dest.flush();
dest.close();
is.close();
}
}
}
I'm having an issue zipping up folders.
I.e. I'll have a folder like this
C:\Lazy\Test
containing files File1.cpp, File2.hpp,.. etc
The zipped up folder looks like C:\Lazy\Test.zip -> Lazy\Test which contains all the cpp and hpp files.
I want to remove the extra subfolders (Lazy\Test) that get created. Why is this happening?
In other words, the zipped up files are not directly underneath the zip file, I have to navigate two more folders to get to them.
Where can I find this issue in the code?
private void zipDirectory() {
File lazyDirectory = new File(defaultSaveLocation);
File[] files = lazyDirectory.listFiles();
for (File file : files) {
if (file.isDirectory()) {
System.out.println("Zipping up " + file);
zipContents(file);
}
}
}
public static void addToZip(String fileName, ZipOutputStream zos) throws FileNotFoundException, IOException {
System.out.println("Writing '" + fileName + "' to zip file");
File file = new File(fileName);
FileInputStream fis = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(fileName);
zos.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zos.write(bytes, 0, length);
}
zos.closeEntry();
fis.close();
}
public static void zipContents(File dirToZip) {
List<File> fileList = new ArrayList<File>();
File[] filesToZip = dirToZip.listFiles();
for (File zipThis : filesToZip) {
String ext = "";
int i = zipThis.toString().lastIndexOf('.');
if (i > 0) {
ext = zipThis.toString().substring(i+1);
}
if(ext.matches("cpp|bem|gz|h|hpp|pl|pln|ppcout|vec|xml|csv")){
fileList.add(zipThis);
}
}
try {
FileOutputStream fos = new FileOutputStream(dirToZip.getName() + ".zip");
ZipOutputStream zos = new ZipOutputStream(fos);
for (File file : fileList) {
addToZip(file.toString(), zos);
}
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Change the addToZip file to take File object. Use it to open the file stream, but only use File#getName to create the ZipEntry, as follows...
public static void addToZip(File file, ZipOutputStream zos) throws FileNotFoundException, IOException {
System.out.println("Writing '" + fileName + "' to zip file");
FileInputStream fis = new FileInputStream(file);
ZipEntry zipEntry = new ZipEntry(file.getName());
zos.putNextEntry(zipEntry);
byte[] bytes = new byte[1024];
int length;
while ((length = fis.read(bytes)) >= 0) {
zos.write(bytes, 0, length);
}
zos.closeEntry();
fis.close();
}
That's it. I have a text file, and I need to move it to a (existing) Zip File in a given directory.
File file = new File("C:\\afolder\\test.txt");
File dir = new File(directoryToGo+"existingzipfile.zip");
boolean success = file.renameTo(new File(dir, file.getName()));
But it does not work. Is there a way to move a file into a existing Zip File?
Thank you.
Hmm you could use something like:
public static void addFilesToExistingZip(File zipFile, File[] files) throws IOException {
// get a temp file
File tempFile = File.createTempFile(zipFile.getName(), null);
// delete it, otherwise you cannot rename your existing zip to it.
tempFile.delete();
boolean renameOk = zipFile.renameTo(tempFile);
if (!renameOk) {
throw new RuntimeException(
"could not rename the file " + zipFile.getAbsolutePath() + " to " + tempFile.getAbsolutePath());
}
byte[] buf = new byte[1024];
ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
ZipEntry entry = zin.getNextEntry();
while (entry != null) {
String name = entry.getName();
boolean notInFiles = true;
for (File f : files) {
if (f.getName().equals(name)) {
notInFiles = false;
break;
}
}
if (notInFiles) { // Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(name)); // Transfer bytes from the ZIP file to the output file
int len;
while ((len = zin.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
entry = zin.getNextEntry();
} // Close the streams
zin.close(); // Compress the files
for (int i = 0; i < files.length; i++) {
InputStream in = new FileInputStream(files[i]); // Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(files[i].getName())); // Transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
} // Complete the entry
out.closeEntry();
in.close();
} // Complete the ZIP file
out.close();
tempFile.delete();
}
Reference:
http://www.dzone.com/snippets/adding-files-existing-jar-file
You'll need to build a new zip file:
Open the existing zip file for reading
Open a new zip file for writing
Copy all the entries from the old zip file to the new one, ignoring an entry corresponding to your extra file, if there is one
Add your extra file
Close both the input and the output files
Delete the old zip file
Rename the new zip file to the old one's name
Starting with Java 7 you have a zip filesystem provider which allows you to write this code:
final Path src = Paths.get("c:\\afolder\\test.txt");
final String filename = src.getFileName().toString();
final Path zip = Paths.get(directoryToGo, "existingzipfile.zip");
final URI uri = URI.create("jar:" + zip.toUri());
final Map<String, ?> env = Collections.emptyMap();
try (
final FileSystem zipfs = FileSystems.newFileSystem(uri, env);
) {
Files.move(src, zipfs.getPath("/" + filename),
StandardCopyOption.REPLACE_EXISTING);
}
You can do like this, here uploadPath+fileName is filename with its path:
String FileName="Urzip file name. zip";
FileOutputStream outputStream = new FileOutputStream(uploadPath+fileName);
ZipOutputStream zipFile = new ZipOutputStream(outputStream);
byte[] buffer = new byte[1024];
// Then, here I have list of pdf files in a LIST:
// continuation ...
for (int i = 0; i < filename.size(); i++) {
String file = filename.get(i);
FileInputStream input = new FileInputStream(uploadPath+file);
ZipEntry entry = new ZipEntry(file);
zipFile.putNextEntry(entry);
int len;
while ((len = input.read(buffer)) > 0) {
zipFile.write(buffer, 0, len);
}
zipFile.closeEntry();
input.close();
}
// Next, here "downFile" is the other file which you have to add in your existing zip:
// continuation ...
FileInputStream input = new FileInputStream(uploadPath+downFile);
ZipEntry e = new ZipEntry(downFile);
zipFile.putNextEntry(e);
int len;
while ((len = input.read(buffer)) > 0) {
zipFile.write(buffer, 0, len);
}
zipFile.closeEntry();
input.close();
zipFile.close();
Adding the class to move the file to inside jar/zip folder based on accepted answer.
The accepted answer didn't hold full executable code ,So i have added the class which helps to move/copy the file to jar/zip
package ZipReader;
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.ZipInputStream;
import java.util.zip.ZipOutputStream;
public class ZipWrite {
public static void main(String args[]) throws IOException
{
File file=new File("F:/MyProjects/New folder/mysql-connector-java-5.1.18-bin.jar");
File filetoPush=new File("F:/MyProjects/New folder/BestResponseTimeBalanceStrategy.class");
File[] files=new File[1];
files[0]=filetoPush;
addFilesToExistingZip(file,files);
}
public static void addFilesToExistingZip(File zipFile, File[] files)
throws IOException {
// get a temp file
File tempFile = File.createTempFile(zipFile.getName(), null);
// delete it, otherwise you cannot rename your existing zip to it.
tempFile.delete();
boolean renameOk = zipFile.renameTo(tempFile);
if (!renameOk) {
throw new RuntimeException("could not rename the file "
+ zipFile.getAbsolutePath() + " to "
+ tempFile.getAbsolutePath());
}
byte[] buf = new byte[1024];
ZipInputStream zin = new ZipInputStream(new FileInputStream(tempFile));
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(zipFile));
ZipEntry entry = zin.getNextEntry();
while (entry != null) {
String name = entry.getName();
boolean notInFiles = true;
for (File f : files) {
if (f.getName().equals(name)) {
System.out.println(name);
notInFiles = false;
break;
}
}
if (notInFiles) {
System.out.println("adding");
// Add ZIP entry to output stream.
out.putNextEntry(new ZipEntry(name)); // Transfer bytes from the
// ZIP file to the
// output file
int len;
while ((len = zin.read(buf)) > 0) {
out.write(buf, 0, len);
}
}
entry = zin.getNextEntry();
} // Close the streams
zin.close(); // Compress the files
for (int i = 0; i < files.length; i++) {
FileInputStream in = new FileInputStream(files[i]);
// Add ZIP entry to output stream.
System.out.println("files[i].getName()-->"+files[i].getName());
out.putNextEntry(new ZipEntry("com/mysql/jdbc/util/"+files[i].getName()));
// Transfer bytes from the file to the ZIP file
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
// Complete the entry
out.closeEntry();
in.close();
}
// Complete the ZIP file
out.close();
tempFile.delete();
}
}
IMO, I thought that epub is a kind of zip . Thus, I've tried to unzip in a way.
public class Main {
public static void main(String argv[ ]) {
final int BUFFER = 2048;
try {
BufferedOutputStream dest = null;
FileInputStream fis = new FileInputStream("/Users/yelinaung/Documents/unzip/epub/doyle.epub");
ZipInputStream zis = new ZipInputStream(new BufferedInputStream(fis));
ZipEntry entry;
while ((entry = zis.getNextEntry()) != null) {
System.out.println("Extracting: " + entry);
int count;
byte data[] = new byte[BUFFER];
// write the files to the disk
FileOutputStream fos = new FileOutputStream("/Users/yelinaung/Documents/unzip/xml/");
dest = new BufferedOutputStream(fos, BUFFER);
while ((count = zis.read(data, 0, BUFFER))
!= -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
zis.close();
} catch ( IOException e) {
e.printStackTrace();
}
}
}
I got that following error ..
java.io.FileNotFoundException: /Users/yelinaung/Documents/unzip/xml (No such file or directory)
though I've created a folder in that way .. and
my way of unzipping epub is right way ? .. Correct Me
I've got the answer.. I haven't checked that the object that have to be extracted is folder or not .
I've corrected in this way .
public static void main(String[] args) throws IOException {
ZipFile zipFile = new ZipFile("/Users/yelinaung/Desktop/unzip/epub/doyle.epub");
String path = "/Users/yelinaung/Desktop/unzip/xml/";
Enumeration files = zipFile.entries();
while (files.hasMoreElements()) {
ZipEntry entry = (ZipEntry) files.nextElement();
if (entry.isDirectory()) {
File file = new File(path + entry.getName());
file.mkdir();
System.out.println("Create dir " + entry.getName());
} else {
File f = new File(path + entry.getName());
FileOutputStream fos = new FileOutputStream(f);
InputStream is = zipFile.getInputStream(entry);
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = is.read(buffer)) != -1) {
fos.write(buffer, 0, bytesRead);
}
fos.close();
System.out.println("Create File " + entry.getName());
}
}
}
Then, got it .
You are creating a FileOutputStream with the same name for every file inside your epub file.
The FileNotFoundException is thrown if the file exists and it is a directory. The first time you pass through the loop, the directory is created and in the next time, the exception is raised.
If you want to change the directory where the epub is extracted, you should do something like this:
FileOutputStream fos = new FileOutputStream("/Users/yelinaung/Documents/unzip/xml/" + entry.getName())
Update
Creating the folder before to extract each file I was able to open the epub file
...
byte data[] = new byte[BUFFER];
String path = entry.getName();
if (path.lastIndexOf('/') != -1) {
File d = new File(path.substring(0, path.lastIndexOf('/')));
d.mkdirs();
}
// write the files to the disk
FileOutputStream fos = new FileOutputStream(path);
...
And to change the folder where the files are extracted, just change the line where the path is defined
String path = "newFolder/" + entry.getName();
This method worked fine for me,
public void doUnzip(String inputZip, String destinationDirectory)
throws IOException {
int BUFFER = 2048;
List zipFiles = new ArrayList();
File sourceZipFile = new File(inputZip);
File unzipDestinationDirectory = new File(destinationDirectory);
unzipDestinationDirectory.mkdir();
ZipFile zipFile;
// Open Zip file for reading
zipFile = new ZipFile(sourceZipFile, ZipFile.OPEN_READ);
// Create an enumeration of the entries in the zip file
Enumeration zipFileEntries = zipFile.entries();
// Process each entry
while (zipFileEntries.hasMoreElements()) {
// grab a zip file entry
ZipEntry entry = (ZipEntry) zipFileEntries.nextElement();
String currentEntry = entry.getName();
File destFile = new File(unzipDestinationDirectory, currentEntry);
if (currentEntry.endsWith(".zip")) {
zipFiles.add(destFile.getAbsolutePath());
}
// grab file's parent directory structure
File destinationParent = destFile.getParentFile();
// create the parent directory structure if needed
destinationParent.mkdirs();
try {
// extract file if not a directory
if (!entry.isDirectory()) {
BufferedInputStream is =
new BufferedInputStream(zipFile.getInputStream(entry));
int currentByte;
// establish buffer for writing file
byte data[] = new byte[BUFFER];
// write the current file to disk
FileOutputStream fos = new FileOutputStream(destFile);
BufferedOutputStream dest =
new BufferedOutputStream(fos, BUFFER);
// read and write until last byte is encountered
while ((currentByte = is.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, currentByte);
}
dest.flush();
dest.close();
is.close();
}
} catch (IOException ioe) {
ioe.printStackTrace();
}
}
zipFile.close();
for (Iterator iter = zipFiles.iterator(); iter.hasNext();) {
String zipName = (String)iter.next();
doUnzip(
zipName,
destinationDirectory +
File.separatorChar +
zipName.substring(0,zipName.lastIndexOf(".zip"))
);
}
}