unzip archive with subfolders in java? - java

I am trying to unzip an archive (test.zip) containing a subfolder with some png images:
test.zip
| -> images
| -> a.png
| -> b.png
Here is what I do:
public static void unzip(String archive, File baseFolder, String[] ignoreExtensions) {
FileInputStream fin;
try {
fin = new FileInputStream(archive);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
while ((ze = zin.getNextEntry()) != null) {
if (ignoreExtensions == null || !ignoreEntry(ze, ignoreExtensions)) {
File destinationFile = new File(baseFolder, ze.getName());
unpackEntry(destinationFile, zin);
}
}
zin.close();
} catch (FileNotFoundException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
private static void unpackEntry(File destinationFile, ZipInputStream zin) {
createParentFolder(destinationFile);
FileOutputStream fout = null;
try {
fout = new FileOutputStream(destinationFile);
for (int c = zin.read(); c != -1; c = zin.read()) {
fout.write(c);
zin.closeEntry();
fout.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
private static void createParentFolder(File destinationFile) {
File parent = new File(destinationFile.getParent());
parent.mkdirs();
}
The images are extracted to the correct location but are corrupt (the size is smaller than expected so I assume they are not decompressed).
If I open the test.zip file with 7Zip it works fine. Any ideas on how to unzip an archive with subfolders?

What are you doing here?
for (int c = zin.read(); c != -1; c = zin.read()) {
fout.write(c);
zin.closeEntry();
fout.close();
}
Could it be that you meant this instead?
for (int c = zin.read(); c != -1; c = zin.read()) {
fout.write(c);
}
zin.closeEntry();
fout.close();

It can be done as below by checking whether the unzipped entry is a directory. If directory then create the directory and proceed with streaming the file inside the directory.
private void unZipFile(long lBatchID, String sFileName) throws Exception {
final int BUFFER = 2048;
BufferedOutputStream dest = null;
FileInputStream fis = null;
ZipInputStream zis = null;
int iSubstr1 = sFileName.indexOf("-");
int iSubstr2 = sFileName.lastIndexOf("-");
int iEDocketSubStr = sFileName.lastIndexOf("\\");
String sBatchNum = sFileName.substring(iSubstr1 + 1,
iSubstr2);
String sEDocketNum = sFileName.substring(iEDocketSubStr + 1,
iSubstr1);
Date startTime = new Date();
try {
fis = new FileInputStream(sFileName);
zis = new ZipInputStream(
new BufferedInputStream(fis));
ZipEntry entry;
String sTempDir = TEMP_DIR + "\\" + sEDocketNum+"-"+sBatchNum;
File fTempDir = new File(sTempDir);
fTempDir.mkdirs();
while ((entry = zis.getNextEntry()) != null) {
int count;
byte data[] = new byte[BUFFER];
if(entry.isDirectory())
{
File f2 = new File(TEMP_DIR + "\\" + sEDocketNum+"-"+sBatchNum+"\\"+entry.getName());
f2.mkdir();
logger.debug("Creating directory during unzip....."+entry.getName());
}
else
{
FileOutputStream fos = new FileOutputStream(new File(sTempDir
+ "\\" + entry.getName()));
dest = new BufferedOutputStream(fos, BUFFER);
while ((count = zis.read(data, 0, BUFFER)) != -1) {
dest.write(data, 0, count);
}
dest.flush();
dest.close();
}
}
zis.close();
LogTaskDuration.logDuration(lBatchID, startTime, "UNZIP");
} catch (Exception e) {
e.printStackTrace();
logger.error("Problem unzipping file - " + sFileName);
throw new Exception(
"Could not create temporary directory to unzip file");
}
finally
{
if(dest != null)
dest.close();
if(fis!=null)
fis.close();
}
}

Related

Java un-compres 5G 7z file

I am trying to decompress a 5G text file with Apache commons compress version 1.9...
public String unZipFile(String pathFileName, String saveFilePath) throws IOException {
SevenZFile sevenZFile = new SevenZFile(new File(pathFileName));
SevenZArchiveEntry entry = sevenZFile.getNextEntry();
try {
while (entry != null) {
if ("deudores.txt".equals(entry.getName())) {
Instant now = Instant.now();
LOG.info("\tunzipping: {} -> {}/{}", pathFileName, saveFilePath, entry.getName());
byte[] buffer = new byte[1024];
File newFile = newFile(new File(saveFilePath), entry.getName());
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = sevenZFile.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
LOG.info("\tunzipping done, took {} secs", now.until(Instant.now(), ChronoUnit.SECONDS));
return saveFilePath+"/"+entry.getName();
}
entry = sevenZFile.getNextEntry();
}
} finally {
sevenZFile.close();
}
return null;
}
public File newFile(File destinationDir, String name) throws IOException {
File destFile = new File(destinationDir, name);
String destDirPath = destinationDir.getCanonicalPath();
String destFilePath = destFile.getCanonicalPath();
if (!destFilePath.startsWith(destDirPath + File.separator)) {
throw new IOException("Entry is outside of the target dir: " + name);
}
return destFile;
}
I am getting only the first 1 GB
Any suggestion / alternatives ? Not a problem to swap to another library.
solved ... iteration over buffer was wrong.

How to release a file in Java GUI without closing

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 want to copy the content of 2 file into third file

I have written code for one file content copy to another file. but i didn't able to copy second file content to third file .
for that i written following code :
try {
File infile = new File("d:\\vijay.txt");
File outfile = new File("d:\\ajay.txt");
FileInputStream instream = new FileInputStream(infile);
FileOutputStream outstream = new FileOutputStream(outfile);
byte[] buffer = new byte[1024];
int length;
while ((length = instream.read(buffer)) > 0) {
outstream.write(buffer, 0, length);
}
instream.close();
outstream.close();
System.out.println("File Copied successfully");
} catch (IOException ioe) {
ioe.printStackTrace();
}
Please help me ,Thanks in advance.
If you have Java 7, I would suggest you use the Files utils. For example:
Path source1 = Paths.get("src1.txt");
Path source2 = Paths.get("src2.txt");
Path destination = Paths.get("dest.txt");
out = Files.newOutputStream(destination, CREATE, APPEND);
Files.copy(source1, destination, StandardCopyOption.REPLACE_EXISTING);
Files.copy(source2, destination);
Do it as below:
try {
// the files to be copied
String[] filePaths = {"file1.txt", "file2.txt"};
// out file
File outfile = new File("d:\\ajay.txt");
FileOutputStream outstream = new FileOutputStream(outfile);
// loop to all files copied
for (String filePath : filePaths) {
FileInputStream instream = new FileInputStream(new File(filePath));
byte[] buffer = new byte[1024];
int length;
while ((length = instream.read(buffer)) > 0) {
outstream.write(buffer, 0, length);
}
// close each file on copy finished
instream.close();
}
// at the end close the output stream
outstream.close();
System.out.println("File Copied successfully");
} catch (IOException ioe) {
ioe.printStackTrace();
}
Now you can copy n files to one file.
You can try this:
try {
File infile = new File("/home/bobo/test/a.txt");
File infile1 = new File("/home/bobo/test/b.txt");
//The third file
File outfile = new File("/home/bobo/test/c.txt");
FileInputStream instream = new FileInputStream(infile);
FileInputStream instream1 = new FileInputStream(infile1);
FileOutputStream outstream = new FileOutputStream(outfile);
byte[] buffer = new byte[1024];
int length;
while ((length = instream.read(buffer)) > 0) {
outstream.write(buffer, 0, length);
}
while ((length = instream1.read(buffer)) > 0) {
outstream.write(buffer, 0, length);
}
instream.close();
instream1.close();
outstream.close();
System.out.println("File Copied successfully");
} catch (IOException ioe) {
ioe.printStackTrace();
}
just give it a try
public class Filescombining
{
public static void main(String[] args) throws IOException
{
ArrayList<String> list = new ArrayList<String>();
try
{
BufferedReader br = new BufferedReader(new FileReader( "input1.txt"));
BufferedReader r = new BufferedReader(new FileReader( "input2.txt"));
String s1 =null;
String s2 = null;
while ((s1 = br.readLine()) != null)
{
list.add(s1);
}
while((s2 = r.readLine()) != null)
{
list.add(s2);
}
}
catch (IOException e)
{
e.printStackTrace();
}
BufferedWriter writer=null;
writer = new BufferedWriter(new FileWriter("output.txt"));
String listWord;
for (int i = 0; i< list.size(); i++)
{
listWord = list.get(i);
writer.write(listWord);
writer.write("\n");
}
System.out.println("completed");
writer.close();
}
}
hope my help works happy coding

Exception in thread "Thread-9" java.lang.OutOfMemoryError: Java heap space

I have been writing an updater for my game.
It checks a .version file on drop box and compares it to the local .version file.
If there is any link missing from the local version of the file, it downloads the required link one by one.
This is the error that it shows
Exception in thread "Thread-9" java.lang.OutOfMemoryError: Java heap space
at com.fox.listeners.ButtonListener.readFile(ButtonListener.java:209)
at com.fox.listeners.ButtonListener.readFile(ButtonListener.java:204)
at com.fox.listeners.ButtonListener.UpdateStart(ButtonListener.java:132)
at com.fox.listeners.ButtonListener$1.run(ButtonListener.java:58)
It only shows for some computers though and not all of them this is the readFile method
private byte[] readFile(URL u) throws IOException {
return readFile(u, getFileSize(u));
}
private static byte[] readFile(URL u, int size) throws IOException {
byte[] data = new byte[size];
int index = 0, read = 0;
try {
HttpURLConnection conn = null;
conn = (HttpURLConnection) u.openConnection();
conn.addRequestProperty("User-Agent", "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)");
InputStream is = conn.getInputStream();
progress_a = 0;
progress_b = data.length;
while(index < data.length) {
read = is.read(data, index, size-index);
index += read;
progress_a = index;
}
} catch(Exception e) {
e.printStackTrace();
}
return data;
}
private byte[] readFile(File f) {
byte[] data = null;
try {
data = new byte[(int)f.length()];
#SuppressWarnings("resource")
DataInputStream dis = new DataInputStream(new FileInputStream(f));
dis.readFully(data);
} catch (IOException e) {
e.printStackTrace();
}
return data;
}
This is the main method that is ran
public void UpdateStart() {
System.out.println("Starting Updater..");
if(new File(cache_dir).exists() == false) {
System.out.print("Creating cache dir.. ");
while(new File(cache_dir).mkdir() == false);
System.out.println("Done");
}
try {
version_live = new Version(new URL(version_file_live));
} catch(MalformedURLException e) {
e.printStackTrace();
}
version_local = new Version(new File(version_file_local));
Version updates = version_live.differences(version_local);
System.out.println("Updated");
int i = 1;
try {
byte[] b = null, data = null;
FileOutputStream fos = null;
BufferedWriter bw = null;
for(String s : updates.files) {
if(s.equals(""))
continue;
System.out.println("Reading file "+s);
AppFrame.pbar.setString("Downloading file "+ i + " of "+updates.files.size());
if(progress_b > 0) {
s = s + " " +(progress_a * 1000L / progress_b / 10.0)+"%";
}
b = readFile(new URL(s));
progress_a = 0;
progress_b = b.length;
AppFrame.pbar.setString("Unzipping file "+ i++ +" of "+updates.files.size());
ZipInputStream zipStream = new ZipInputStream(new ByteArrayInputStream(b));
File f = null, parent = null;
ZipEntry entry = null;
int read = 0, entry_read = 0;
long entry_size = 0;
progress_b = 0;
while((entry = zipStream.getNextEntry()) != null)
progress_b += entry.getSize();
zipStream = new ZipInputStream(new ByteArrayInputStream(b));
while((entry = zipStream.getNextEntry()) != null) {
f = new File(cache_dir+entry.getName());
if(entry.isDirectory())
continue;
System.out.println("Making file "+f.toString());
parent = f.getParentFile();
if(parent != null && !parent.exists()) {
System.out.println("Trying to create directory "+parent.getAbsolutePath());
while(parent.mkdirs() == false);
}
entry_read = 0;
entry_size = entry.getSize();
data = new byte[1024];
fos = new FileOutputStream(f);
while(entry_read < entry_size) {
read = zipStream.read(data, 0, (int)Math.min(1024, entry_size-entry_read));
entry_read += read;
progress_a += read;
fos.write(data, 0, read);
}
fos.close();
}
bw = new BufferedWriter(new FileWriter(new File(version_file_local), true));
bw.write(s);
bw.newLine();
bw.close();
}
} catch(Exception e) {
e.printStackTrace();
return;
}
System.out.println(version_live);
System.out.println(version_local);
System.out.println(updates);
CacheUpdated = true;
if(CacheUpdated) {
AppFrame.pbar.setString("All Files are downloaded click Launch to play!");
}
}
I don't get why it is working for some of my players and then some of my other players it does not i have been trying to fix this all day and i am just so stumped at this point but this seems like its the only big issue left for me to fix.
Either increase the memory allocated to your JVM (How can I increase the JVM memory?), or make sure that the file being loaded in memory isn't gigantic (if it is, you'll need to find an alternate solution, or just read chunks of it at a time instead of loading the entire thing in memory).
Do your update in several steps. Here's some pseudo-code with Java 8. It's way shorter than what you wrote because Java has a lot of built-in tools that you re-write much less efficiently.
// Download
Path zipDestination = Paths.get(...);
try (InputStream in = source.openStream()) {
Files.copy(in, zipDestination);
}
// Unzip
try (ZipFile zipFile = new ZipFile(zipDestination.toFile())) {
for (ZipEntry e: Collections.list(zipFile.entries())) {
Path entryDestination = Paths.get(...);
Files.copy(zipFile.getInputStream(e), entryDestination);
}
}
// Done.

Creating Folders in a Zip Folder in Java [duplicate]

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();
}
}
}
}

Categories

Resources