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();
}
Related
Well, it is as simple as the title.
I tried for many hours to make a method that will take the archive file and a File[] (the files that will be added to the archive) and I only made it to the point that the method adds new files into the archive, but if a file with the same name of a file that I'm trying to add already exists, it throws me an error.
I tried searching for a solution but didn't find any.
Can you help me make a method that will take two parameters: File archive, File[] fileToAdd. That will add files to an archive and if needed will override existing files?
Thank you, TheRedCoder
Edit:
Here is my current code
public static void addFilesToZip(File zipFile, File[] files) throws IOException {
File tempFile = File.createTempFile(zipFile.getName(), null);
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) {
File file = null;
String name = entry.getName();
boolean notInFiles = true;
for (File f : files) {
if (f.getName().equals(name)) {
notInFiles = false;
file = f;
break;
}
}
if (notInFiles) {
out.putNextEntry(new ZipEntry(name));
int len;
while ((len = zin.read(buf)) > 0) {
out.write(buf, 0, len);
}
} else {
/**
*
* I'm stuck here, what should i do here?
*
*/
}
entry = zin.getNextEntry();
}
zin.close();
for (int i = 0; i < files.length; i++) {
InputStream in = new FileInputStream(files[i]);
out.putNextEntry(new ZipEntry(files[i].getName()));
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.closeEntry();
in.close();
}
out.close();
tempFile.delete();
}
This question already has answers here:
directories in a zip file when using java.util.zip.ZipOutputStream
(6 answers)
Closed 9 years ago.
My task requires me to save a file directory into a zip folder. My only problem is I need to keep the sub-folders as folders from the main Directory. The file system will look something like
C\\Friends
C:\\Friends\\Person1\\Information.txt
C:\\Friends\\Person2\\Information.txt
C:\\Friends\\Person3\\Information.txt
.
.
.
Right now I am able to write just the txt files inside of my zip folder, but in my zip folder I need to keep that folder structure. I know the way my code is right now will tell me the file I'm trying to write is closed(No access). My Functions thus far:
private String userDirectroy = "" //This is set earlier in the program
public void exportFriends(String pathToFile)
{
String source = pathToFile + ".zip";
try
{
String sourceDir = userDirectory;
String zipFile = source;
try
{
FileOutputStream fout = new FileOutputStream(zipFile);
ZipOutputStream zout = new ZipOutputStream(fout);
File fileSource = new File(sourceDir);
addDirectory(zout, fileSource);
zout.close();
System.out.println("Zip file has been created!");
}
catch(Exception e)
{
}
}
catch(Exception e)
{
System.err.println("First Function: " + e);
}
}
private static void addDirectory(ZipOutputStream zout, File fileSource) {
File[] files = fileSource.listFiles();
System.out.println("Adding directory " + fileSource.getName());
for(int i=0; i < files.length; i++)
{
if(files[i].isDirectory())
{
try
{
byte[] buffer = new byte[1024];
FileInputStream fin = new FileInputStream(files[i]);
zout.putNextEntry(new ZipEntry(files[i].getName()));
int length;
while((length = fin.read(buffer)) > 0)
{
zout.write(buffer, 0, length);
}
}
catch(Exception e)
{
System.err.println(e);
}
addDirectory(zout, files[i]);
continue;
}
try
{
System.out.println("Adding file " + files[i].getName());
//create byte buffer
byte[] buffer = new byte[1024];
//create object of FileInputStream
FileInputStream fin = new FileInputStream(files[i]);
zout.putNextEntry(new ZipEntry(files[i].getName()));
int length;
while((length = fin.read(buffer)) > 0)
{
zout.write(buffer, 0, length);
}
zout.closeEntry();
//close the InputStream
fin.close();
}
catch(IOException ioe)
{
System.out.println("IOException :" + ioe);
}
}
}
Any help would be much appreciated. Thank You
For each folder, you need to add a empty ZipEntry of the path.
For each file, you need to supply both the path and file name. This will require you to know the part of the path to strip off, this would be everything after the start directory
Expanded concept
So, from your example, if the start directory is C:\Friends, then the entry for C:\Friends\Person1\Information.txt should look like Person1\Information.txt
public void exportFriends(String pathToFile) {
String source = pathToFile + ".zip";
try {
String sourceDir = "C:/Friends";
String zipFile = source;
try {
FileOutputStream fout = new FileOutputStream(zipFile);
ZipOutputStream zout = new ZipOutputStream(fout);
File fileSource = new File(sourceDir);
addDirectory(zout, sourceDir, fileSource);
zout.close();
System.out.println("Zip file has been created!");
} catch (Exception e) {
e.printStackTrace();
}
} catch (Exception e) {
e.printStackTrace();
}
}
public static String getRelativePath(String sourceDir, File file) {
// Trim off the start of source dir path...
String path = file.getPath().substring(sourceDir.length());
if (path.startsWith(File.pathSeparator)) {
path = path.substring(1);
}
return path;
}
private static void addDirectory(ZipOutputStream zout, String sourceDir, File fileSource) throws IOException {
if (fileSource.isDirectory()) {
// Add the directory to the zip entry...
String path = getRelativePath(sourceDir, fileSource);
if (path.trim().length() > 0) {
ZipEntry ze = new ZipEntry(getRelativePath(sourceDir, fileSource));
zout.putNextEntry(ze);
zout.closeEntry();
}
File[] files = fileSource.listFiles();
System.out.println("Adding directory " + fileSource.getName());
for (int i = 0; i < files.length; i++) {
if (files[i].isDirectory()) {
addDirectory(zout, sourceDir, files[i]);
} else {
System.out.println("Adding file " + files[i].getName());
//create byte buffer
byte[] buffer = new byte[1024];
//create object of FileInputStream
FileInputStream fin = new FileInputStream(files[i]);
zout.putNextEntry(new ZipEntry(getRelativePath(sourceDir, files[i])));
int length;
while ((length = fin.read(buffer)) > 0) {
zout.write(buffer, 0, length);
}
zout.closeEntry();
//close the InputStream
fin.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"))
);
}
}
If My Application wants to zip the Resultant files(group of Files) using java in a dynamic way, what are the available options in Java?
When i Browsed I have got java.util.zip package to use, but is there any other way where I can use it to implement?
public class FolderZiper {
public static void main(String[] a) throws Exception {
zipFolder("c:\\a", "c:\\a.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);
}
}
}
}
The original Java implementation is known to have some bugs related to files encoding. For example it can't properly handle filenames with umlauts.
TrueZIP is an alternative that we've used in our project: https://truezip.dev.java.net/
Check the documentation on the site.
You can use ZIP file handling library that comes with JDK
Also this tutorials might be helpful.
Java have a java.util.zip.ZipInputStream and along with this you can use ZipEntry ... Something like
public static void unZipIt(String zipFile, String outputFolder){
File folder = new File(zipFile);
List<String> files = listFilesForFolder(folder);
System.out.println("Size " + files.size());
byte[] buffer = new byte[1024];
try{
Iterator<String> iter = files.iterator();
while(iter.hasNext()){
String file = iter.next();
System.out.println("file name " + file);
ZipInputStream zis = new ZipInputStream(new FileInputStream(file));
ZipEntry ze = zis.getNextEntry();
while(ze!=null){
String fileName = ze.getName();
File newFile = new File(outputFolder + File.separator + fileName);
System.out.println("file unzip : "+ newFile.getAbsoluteFile());
new File(newFile.getParent()).mkdirs();
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
ze = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
System.out.println("Done");
}
}catch(IOException ex){
ex.printStackTrace();
}
}