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"))
);
}
}
Related
I've created a pretty simple Java GUI to browse/load a zip file on Windows platform to begin unzipping and then do some file checking.
Everything works fine except that I have to close the GUI window in order to delete the zip file that has been opened in the GUI.In my finally block of the unzipping method, I've tried adding the following:
public static String unZip(String path)
{
int count = -1;
String savepath = "";
File file = null;
InputStream is = null;
FileOutputStream fos = null;
BufferedOutputStream bos = null;
savepath = path.substring(0, path.lastIndexOf("\\")) + File.separator; //File saving directory
new File(savepath).mkdir(); //create the saving directory
ZipFile zipFile = null;
String topLevelDirName="";
try
{
zipFile = new ZipFile(path,Charset.forName("gbk")); //Encoding
Enumeration<?> entries = zipFile.entries();
int levelCount=0;
while(entries.hasMoreElements())
{
byte buf[] = new byte[buffer];
ZipEntry entry = (ZipEntry)entries.nextElement();
String filename = entry.getName();
boolean ismkdir = false;
if(filename.lastIndexOf("/") != -1){ //To check if there is a directory
ismkdir = true;
}
filename = savepath + filename;
if(entry.isDirectory()){ //If it is a directory
levelCount++;
file = new File(filename);
file.mkdirs();
if(levelCount==1)
topLevelDirName = filename;
continue;
}
file = new File(filename);
if(!file.exists()){
if(ismkdir){
new File(filename.substring(0, filename.lastIndexOf("/"))).mkdirs();
}
}
file.createNewFile(); //Create the file
is = zipFile.getInputStream(entry);
fos = new FileOutputStream(file);
bos = new BufferedOutputStream(fos, buffer);
while((count = is.read(buf)) > -1)
{
bos.write(buf, 0, count);
}
bos.flush();
bos.close();
fos.close();
is.close();
}
zipFile.close();
}catch(IOException ioe){
ioe.printStackTrace();
}finally{
try{
if(bos != null){
bos.close();
}
if(fos != null) {
fos.close();
}
if(is != null){
is.close();
}
if(zipFile != null){
zipFile.close();
}
}catch(Exception e) {
e.printStackTrace();
}
return topLevelDirName;
}
}
However, I am still not able to delete the zip unless explicitly close the GUI.
Wonder if there is anything to do with the Windows file handle?Thanks in advance.
Java 8 introduced the try-with-resources Statement to make this kind of situation simpler and cleaner.
One of the issues you have is, if any one of the attempts to close the many resources you have open fails, then none of the others will be closed
public static String unZip(String path) throws IOException {
int count = -1;
File sourceFile = new File(path);
String name = sourceFile.getName();
name = name.substring(0, name.lastIndexOf(".zip"));
File sourcePath = new File(sourceFile.getParent(), name);
System.out.println("SavePath = " + sourcePath);
if (!sourcePath.exists() && !sourcePath.mkdirs()) {
throw new IOException("Could not create directory " + sourcePath);
}
String topLevelDirName = "";
try (ZipFile zipFile = new ZipFile(sourceFile)) {
Enumeration<?> entries = zipFile.entries();
int levelCount = 0;
byte buf[] = new byte[1024];
while (entries.hasMoreElements()) {
ZipEntry entry = (ZipEntry) entries.nextElement();
String filename = entry.getName();
File file = new File(sourcePath, filename);
if (entry.isDirectory()) { //If it is a directory
levelCount++;
System.out.println("Make directory " + file);
if (!file.exists() && !file.mkdirs()) {
throw new IOException("Could not create directory " + filename);
}
} else {
System.out.println("Extract to " + file);
try (InputStream is = zipFile.getInputStream(entry);
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(file))) {
while ((count = is.read(buf)) > -1) {
bos.write(buf, 0, count);
}
}
}
}
}
return topLevelDirName;
}
I've update the code slightly to try and make it a little cleaner and simpler and to take advantage of the available APIs
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();
}
}
}
When I download a ZIP file from Amazon S3 and extract it using Java, it does not preserve the original timestamp of the file inside the ZIP.
Why? Here's the uncompress Java code:
public void unzipFile(String zipFile, String newFile) {
try {
FileInputStream fis = new FileInputStream(zipFile);
BufferedInputStream bis = new BufferedInputStream(fis);
ZipInputStream zis = new ZipInputStream(bis);
FileOutputStream fos = new FileOutputStream(newFile);
final byte[] buffer = new byte[1024];
int len = 0;
while ((len = zis.read(buffer)) != -1) {
fos.write(buffer, 0, len);
}
//close resources
fos.close();
zis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Basically, I want the timestamp of the file inside of the zip file, say file X has JAN-01-2010 to be preserved. But file X's is overwridden with the timestamp of the ZIP file, which has SEP-20-2013.
It's because you are putting the contents of the Zip File into a new File.
You could try something like:
public void unzipFile(String zipFile, String outputFolder){
try {
byte[] buffer = new byte[1024];
File folder = new File(outputFolder);
if(!folder.exists()){
folder.mkdir();
}
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFile));
ZipEntry ze = zis.getNextEntry();
while(ze!=null){
String fileName = ze.getName();
File newFile = new File(outputFolder + File.separator + fileName);
//create all non exists folders
//else you will hit FileNotFoundException for compressed folder
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();
newFile.setLastModified(ze.getTime());
ze = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
} catch (IOException e) {
e.printStackTrace();
}
}
Pulled from: http://www.mkyong.com/java/how-to-decompress-files-from-a-zip-file/ With Modifications to add Modified Time.
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();
}
}