I want to extract a zip file which contains a jar file. This file has complex folder structure and in one of the folders there is a jar file. When I am trying to use the following code to extract the jar file the program goes in infinite loop in reading the jar file and never recovers. It keeps on writing the contents of the jar till we reach the limit of the disc space even though the jar is of only a few Mbs.
Please find the code snippet below
`
// using a ZipInputStream to get the zipIn by passing the zipFile as FileInputStream
ZipEntry entry = zipIn.getNextEntry();
String fileName= entry.getName()
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileName));
byte[] bytesIn = new byte[(int)bufferSize];
while (zipIn.read(bytesIn) > 0) // This is the part where the loop does not end
{
bos.write(bytesIn);
}
..
// flushing an closing the bos
Please let me know if there is any way we can avoid this and get the jar file out at required location.
Does this suit your needs?
public static void main(String[] args) {
try {
copyJarFromZip("G:\\Dateien\\Desktop\\Desktop.zip",
"G:\\Dateien\\Desktop\\someJar.jar");
} catch (IOException ex) {
ex.printStackTrace();
}
}
public static void copyJarFromZip(final String zipPath, final String targetPath) throws IOException {
try (ZipFile zipFile = new ZipFile(zipPath)) {
for (final Enumeration<? extends ZipEntry> e = zipFile.entries(); e.hasMoreElements();) {
ZipEntry zipEntry = e.nextElement();
if (zipEntry.getName().endsWith(".jar")) {
Files.copy(zipFile.getInputStream(zipEntry), Paths.get(targetPath),
StandardCopyOption.REPLACE_EXISTING);
}
}
}
}
Related
i have checked everywhere online and stackoverflow and could not find a match specific to this issue.
I am trying to extract a pdf file that is located in a zip file that is inside a zip file (nested zips).
Re-calling the method i am using to extract does not work nor does changing the whole program to accept Inputstreams instead of how i am doing it below.
The .pdf file inside the nested zip is just skipped at this stage
public static void main(String[] args)
{
try
{
//Paths
String basePath = "C:\\Users\\user\\Desktop\\Scan\\";
File lookupDir = new File(basePath + "Data\\");
String doneFolder = basePath + "DoneUnzipping\\";
File[] directoryListing = lookupDir.listFiles();
for (int i = 0; i < directoryListing.length; i++)
{
if (directoryListing[i].isFile()) //there's definately a file
{
//Save the current file's path
String pathOrigFile = directoryListing[i].getAbsolutePath();
Path origFileDone = Paths.get(pathOrigFile);
Path newFileDone = Paths.get(doneFolder + directoryListing[i].getName());
//unzip it
if(directoryListing[i].getName().toUpperCase().endsWith(ZIP_EXTENSION)) //ZIP files
{
unzip(directoryListing[i].getAbsolutePath(), DESTINATION_DIRECTORY + directoryListing[i].getName());
//move to the 'DoneUnzipping' folder
Files.move(origFileDone, newFileDone);
}
}
}
} catch (Exception e)
{
e.printStackTrace(System.out);
}
}
private static void unzip(String zipFilePath, String destDir)
{
//buffer for read and write data to file
byte[] buffer = new byte[BUFFER_SIZE];
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFilePath)))
{
FileInputStream fis = new FileInputStream(zipFilePath);
ZipEntry ze = zis.getNextEntry();
while(ze != null)
{
String fileName = ze.getName();
int index = fileName.lastIndexOf("/");
String newFileName = fileName.substring(index + 1);
File newFile = new File(destDir + File.separator + newFileName);
//Zips inside zips
if(fileName.toUpperCase().endsWith(ZIP_EXTENSION))
{
ZipInputStream innerZip = new ZipInputStream(zis);
ZipEntry innerEntry = null;
while((innerEntry = innerZip.getNextEntry()) != null)
{
System.out.println("The file: " + fileName);
if(fileName.toUpperCase().endsWith("PDF"))
{
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = innerZip.read(buffer)) > 0)
{
fos.write(buffer, 0, len);
}
fos.close();
}
}
}
//close this ZipEntry
zis.closeEntry(); // java.io.IOException: Stream Closed
ze = zis.getNextEntry();
}
//close last ZipEntry
zis.close();
fis.close();
} catch (IOException e)
{
e.printStackTrace();
}
}
The solution to this is not as obvious as it seems. Despite writing a few zip utilities myself some time ago, getting zip entries from inside another zip file only seems obvious in retrospect
(and I also got the java.io.IOException: Stream Closed on my first attempt).
The Java classes for ZipFile and ZipInputStream really direct your thinking into using the file system, but it is not required.
The functions below will scan a parent-level zip file, and continue scanning until it finds an entry with a specified name. (Nearly) everything is done in-memory.
Naturally, this can be modified to use different search criteria, find multiple file types, etc. and take different actions, but this at least demonstrates the basic technique in question -- zip files inside of zip files -- no guarantees on other aspects of the code, and someone more savvy could most likely improve the style.
final static String ZIP_EXTENSION = ".zip";
public static byte[] getOnePDF() throws IOException
{
final File source = new File("/path/to/MegaData.zip");
final String nameToFind = "FindThisFile.pdf";
final ByteArrayOutputStream mem = new ByteArrayOutputStream();
try (final ZipInputStream in = new ZipInputStream(new BufferedInputStream(new FileInputStream(source))))
{
digIntoContents(in, nameToFind, mem);
}
// Save to disk, if you want
// copy(new ByteArrayInputStream(mem.toByteArray()), new FileOutputStream(new File("/path/to/output.pdf")));
// Otherwise, just return the binary data
return mem.toByteArray();
}
private static void digIntoContents(final ZipInputStream in, final String nameToFind, final ByteArrayOutputStream mem) throws IOException
{
ZipEntry entry;
while (null != (entry = in.getNextEntry()))
{
final String name = entry.getName();
// Found the file we are looking for
if (name.equals(nameToFind))
{
copy(in, mem);
return;
}
// Found another zip file
if (name.toUpperCase().endsWith(ZIP_EXTENSION.toUpperCase()))
{
digIntoContents(new ZipInputStream(new ByteArrayInputStream(getZipEntryFromMemory(in))), nameToFind, mem);
}
}
}
private static byte[] getZipEntryFromMemory(final ZipInputStream in) throws IOException
{
final ByteArrayOutputStream mem = new ByteArrayOutputStream();
copy(in, mem);
return mem.toByteArray();
}
// General purpose, reusable, utility function
// OK for binary data (bad for non-ASCII text, use Reader/Writer instead)
public static void copy(final InputStream from, final OutputStream to) throws IOException
{
final int bufferSize = 4096;
final byte[] buf = new byte[bufferSize];
int len;
while (0 < (len = from.read(buf)))
{
to.write(buf, 0, len);
}
to.flush();
}
Your question asks how to use java (by implication in windows) to extract a pdf from a zip inside another outer zip.
In many systems including windows it is a single line command that will depend on the location of source and target folders, however using the shortest example of current downloads folder it would be in a shell as simple as
tar -xf "german (2).zip" && tar -xf "german.zip" && german.pdf
to shell the command in windows see
How do I execute Windows commands in Java?
The default pdf viewer can open the result so Windows Edge or in my case SumatraPDF
There is generally no point in putting a pdf inside a zip because it cannot be run in there. So single nesting would be advisable if needed for download transportation.
There is no need to add a password to the zip because PDF uses its own password for opening. Thus unwise to add two levels of complexity. Keep it simple.
If you have multiple zips nested inside multiple zips with multiple pdfs in each then you have to be more specific by filtering names. However avoid that extra onion skin where possible.
\Downloads>tar -xf "german (2).zip" "both.zip" && tar -xf "both.zip" "English language.pdf"
You could complicate that by run in a memory or temp folder but it is reliable and simple to use the native file system so consider without Java its fastest to run
CD /D "C:/Users/user/Desktop/Scan/DoneUnzipping" && for %f in (..\Data\*.zip) do tar -xf "%f" "*.zip" && for %f in (*.zip) do tar -xf "%f" "*.pdf" && del "*.zip"
This will extract all inner zips into working folder then extract all PDFs and remove all the essential temporary zips. The source double zips will not be deleted simply touched.
The line that causes your problem looks to be auto-close block you have created when reading the inner zip:
try(ZipInputStream innerZip = new ZipInputStream(fis)) {
...
}
Several likely issues: firstly it is reading the wrong stream - fis not the existing zis.
Secondly, you shouldn't use try-with-resources for auto-close on innerZip as this implicitly calls innerZip.close() when exiting the block. If you view the source code of ZipInputStream via a good IDE you should see (eventually) that ZipInputStream extends InflaterInputStream which itself extends FilterInputStream. A call to innerZip.close() will close the underlying outer stream zis (fis in your case) hence stream is closed when you resume the next entry of the outer zip.
Therefore remove the try() block and add use of zis:
ZipInputStream innerZip = new ZipInputStream(zis);
Use try-catch block only for the outermost file handling:
try (ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFilePath))) {
ZipEntry ze = zis.getNextEntry();
...
}
Thirdly, you appear to be copying the wrong stream when extracting a PDF - use innerZip not outer zis. The code will never extract PDF as these 2 lines can never be true at the same time because a file ending ZIP will never end PDF too:
if(fileName.toUpperCase().endsWith(ZIP_EXTENSION)) {
...
// You want innerEntry.getName() here
if(fileName.toUpperCase().endsWith("PDF"))
You should be able to switch to one line Files.copy and make use of the PDF filename not zip filename:
if(innerEntry.getName().toUpperCase().endsWith("PDF")) {
Path newFile = Paths.get(destDir + '-'+innerEntry.getName().replace("/", "-"));
System.out.println("Files.copy to " + newFile);
Files.copy(innerZip, newFile);
}
I am trying to write multiple files into a directory and a zip file. that directory and zip file are supposed to be contained in another zip. so my desired zip structure would look like this:
parent.zip
- testDirectory/
- testZip.zip
When I read my files into a byte[] and write them into my directory testDirectory nothing is written into the directory. the directory is empty when I open my zip.
On the other hand when I write my byte[] array into a zip file called testZip.zip the files will be correctly written into the zip file.
parent.zip, testDirectory/ and testZip.zip are all being created. the only problem is that testDirectory/ is empty.
What is the solution to my problem?
private void addFiles(Document document, ZipOutputStream zos) throw FileNotFoundException, IOException {
byte[] mediaFilesDirectory = getMediaFiles();
ZipEntry entry = new ZipEntry(document.getId() + File.separator + "testDirectory/");
entry.setSize(mediaFilesDirectory.length);
zos.putNextEntry(entry);
zos.write(mediaFilesDirectory);
zos.closeEntry();
ZipEntry entry2 = new ZipEntry(document.getId() + File.separator + "testZip.zip");
entry2.setSize(mediaFilesDirectory.length);
zos.putNextEntry(entry2);
zos.write(mediaFilesDirectory);
zos.closeEntry();
}
private byte[] getMediaFiles() throws FileNotFoundException {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(baos)) {
byte[] bytes = "Hello World".getBytes();
String entryName = "test.txt";
ZipEntry entry = new ZipEntry(entryName);
entry.setSize(bytes.length);
zos.putNextEntry(entry);
zos.write(bytes);
zos.closeEntry();
zos.close();
return baos.toByteArray();
} catch (Exception exc) {
throw new FileNotFoundException("Exception");
}
}
No Exceptions are being thrown. If I comment out the ZipEntry for testDirectory/, then testZip.zip will still correctly be created. If I comment out testZip.zip, then testDirectory/ will still be empty.
Here some test code to run locally. it suffers from the same problem as my code:
import java.io.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipOutputStream;
public class Main {
public static void main(String[] args) {
System.out.println("Make sure to change the file variable");
File file = new File("C:\\Users\\YourUser\\test.zip"); //TODO enter a valid path here
try(ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(file))) {
addFiles(zos);
zos.closeEntry();
} catch (Exception e) {
System.out.println(e);
}
}
private static void addFiles(ZipOutputStream zos) throws Exception {
byte[] mediaFilesDirectory = getMediaFiles();
ZipEntry entry = new ZipEntry("1" + File.separator + "testDirectory/");
entry.setSize(mediaFilesDirectory.length);
zos.putNextEntry(entry);
zos.write(mediaFilesDirectory);
zos.closeEntry();
ZipEntry entry2 = new ZipEntry("1" + File.separator + "testZip.zip");
entry2.setSize(mediaFilesDirectory.length);
zos.putNextEntry(entry2);
zos.write(mediaFilesDirectory);
zos.closeEntry();
}
private static byte[] getMediaFiles() throws Exception {
try (ByteArrayOutputStream baos = new ByteArrayOutputStream(); ZipOutputStream zos = new ZipOutputStream(baos)) {
byte[] bytes = "Hello World".getBytes();
String entryName = "test.txt";
ZipEntry entry = new ZipEntry(entryName);
entry.setSize(bytes.length);
zos.putNextEntry(entry);
zos.write(bytes);
zos.closeEntry();
zos.close();
return baos.toByteArray();
}
}
}
ZipEntry entry = new ZipEntry(document.getId() + File.separator + "testDirectory/");
entry.setSize(mediaFilesDirectory.length);
zos.putNextEntry(entry);
zos.write(mediaFilesDirectory);
zos.closeEntry();
This code makes no sense.
It creates a directory, and directories do not themselves contain anything. In a zip file, a directory is just a string, a marker to the unzip tool: Make this dir.
A zip file is JUST a mapping of strings representing filenames to data representing the contents, that is it, zip files are not hierarchical.
If you want to write 'foo.txt' into the zip file as well as 'subdir/bar.txt', you would do:
ZipEntry entry = new ZipEntry("foo.txt");
zos.putNextEntry(entry);
zos.write(dataOfFooTxt);
ZipEntry entry = new ZipEntry("subdir/");
zos.putNextEntry(entry);
ZipEntry entry = new ZipEntry("subdir/bar.txt");
zos.putNextEntry(entry);
zos.write(dataOfBarTxt);
You just put an entry and do nothing further. Note also that zips always use forward slash for pathing, File.separator is something you should never use in java, except for one sole purpose: Creating strings fit to show to users. That's all. forward slash is the path separator for java apps. Even if they run on windows.
What you are attempting to do (make a zip which you the nwant to put in a zip) would result in the command:
unzip myzip.zip
To unpack 2 files: 'test.txt' and 'innerzip.zip', which is, itself a zip file. This can be done but is really weird, and certainly doesn't compress things any better. I'm not sure if that is your intent or if you're just confused and you think this is how you put subdirs in zip files. If it's the latter - just do what the second snippet in this answer does - do not make zips-in-zips.
I have file in the following structure:
--BA.zip
|
|--- BA (directory)
|
|---BA_KKSSI_20201013.zip
| |
| |---BA_KKSSI_20201013.txt
|---BA_KKSSI_20201014.zip
| |
| |---BA_KKSSI_20201014.txt
|---BA_KKSSI_20201015.zip
|
|---BA_KKSSI_20201015.txt
I need to read BA_KKSSI_20201013.txt without extracting the parent file which is BA.zip
I have already written parts of code to read if there is no sub dirs. For example:
public static String readChildZip(Path zipPath) throws IOException {
try (ZipFile zipFile = new ZipFile(zipPath.toFile())) {
// since there is only one text file
ZipEntry textFile = zipFile.entries().nextElement();
// the zip
System.out.println(zipFile.getName());
InputStream is = zipFile.getInputStream(textFile);
String contents = IOUtils.toString(is, StandardCharsets.UTF_8);
return contents;
}
}
Above code can process the last zip and txt part (i.e., if there are no sub-dirs within a zip)
I looked through most of the SO posts and all of them propose extracting the sub-directory first and then read through the secondary zip files.
Is there a way to do this without extracting in the first place?
You can use ZipInputStream (https://docs.oracle.com/javase/7/docs/api/java/util/zip/ZipInputStream.html) to read entries in the "outer" zip file as zip files as well.
Meaning open the zip file as you have but then iterate over and if a entry is a zipfile itself you create a ZipInputStream with the InputStream for that ZipEntry.
This returns the contents of the first text file inside the first Zip file in zipPath.
public static String readChildZip(Path zipPath) throws IOException {
try (ZipFile zipFile = new ZipFile(zipPath.toFile())) {
ZipEntry childZipEntry = zipFile.entries().nextElement();
try (InputStream childInputStream = zipFile.getInputStream(childZipEntry);
ZipInputStream childZipStream = new ZipInputStream(childInputStream)) {
childZipStream.getNextEntry();
return new String(childZipStream.readAllBytes(), StandardCharsets.UTF_8);
}
}
}
And this will print the contents of all text files inside the first Zip file in zipPath.
public static void readChildZipAll(Path zipPath) throws IOException {
try (ZipFile zipFile = new ZipFile(zipPath.toFile())) {
ZipEntry childZipEntry = zipFile.entries().nextElement();
try (InputStream childInputStream = zipFile.getInputStream(childZipEntry);
ZipInputStream childZipStream = new ZipInputStream(childInputStream)) {
ZipEntry grandChildEntry;
while ((grandChildEntry = childZipStream.getNextEntry()) != null) {
System.out.println(grandChildEntry + ":"
+ new String(childZipStream.readAllBytes(), StandardCharsets.UTF_8));
}
}
}
}
You should look at using NIO ZIP File System or ZipInputStream if wanting to scan a ZIP.
Here is an example of using ZIP File System in a recursive scanner which can be used to inspect any level of depth of JAR/ZIP/WAR/EAR hierarchy. You should adapt to suit own purposes for whatever action you need to perform on the content, this example just cats any ".txt" files to the console.
Note that ZIP File System returns zip filesystem Path objects which can be used with NIO Files.xxx() calls such as Files.find() and Find.copy() just like you would use for Path that originate from default HDD filesystems.
private static Pattern ZIP_PATTERN = Pattern.compile("(?i).*\\.(jar|war|ear|zip)");
public static void traverseZip(Path zip) {
System.out.println("traverseZip "+zip.toAbsolutePath());
try (FileSystem fs = FileSystems.newFileSystem(zip)) {
for (Path root : fs.getRootDirectories()) {
try (Stream<Path> stream = Files.find(root, Integer.MAX_VALUE, (p,a) -> true)) {
stream.forEach(entry -> {
System.out.println(zip.toString()+" -> "+entry);
// SOME ACTION HERE, for example
if (entry.toString().endsWith(".txt")) {
cat(entry, System.out);
}
if (ZIP_PATTERN.matcher(entry.toString()).matches() && Files.isRegularFile(entry)) {
traverseZip(entry);
}
});
}
}
}
catch(IOException e) {
throw new UncheckedIOException(e);
}
}
private static void cat(Path path, OutputStream out) {
try {
Files.copy(path, out);
} catch (IOException e) {
throw new UncheckedIOException(e);
}
}
Launch with:
traverseZip(Path.of("some.zip"));
This question already has answers here:
How to unzip files recursively in Java?
(10 answers)
Closed last month.
I have program when I give a zip folder path via console. It will go through each item inside that folder (every child item, children of child, etc..). But if it encounters a zip folder it will ignore everything inside the zip folder, I need to read everything including files inside zip folders.
Here is the method that goes through each item:
public static String[] getLogBuffers(String path) throws IOException//path is given via console
{
String zipFileName = path;
String destDirectory = path;
BufferedInputStream errorLogBuffer = null;
BufferedInputStream windowLogBuffer = null;
String strErrorLogFileContents="";
String strWindowLogFileContents="";
String[] errorString=new String[2];
byte[] buffer = new byte[1024];
ZipInputStream zis = new ZipInputStream(new FileInputStream(zipFileName));
ZipEntry zipEntry = zis.getNextEntry();
while (zipEntry != null)
{
String filePath = destDirectory + "/" + zipEntry.getName();
System.out.println("unzipping" + filePath);
if (!zipEntry.isDirectory())
{
if (zipEntry.getName().endsWith("errorlog.txt"))
{
ZipFile zipFile = new ZipFile(path);
InputStream errorStream = zipFile.getInputStream(zipEntry);
BufferedInputStream bufferedInputStream=new BufferedInputStream(errorStream);
byte[] contents = new byte[1024];
System.out.println("ERRORLOG NAME"+zipEntry.getName());
int bytesRead = 0;
while((bytesRead = bufferedInputStream.read(contents)) != -1) {
strErrorLogFileContents += new String(contents, 0, bytesRead);
}
}
if (zipEntry.getName().endsWith("windowlog.txt"))
{ ZipFile zipFile = new ZipFile(path);
InputStream windowStream = zipFile.getInputStream(zipEntry);
BufferedInputStream bufferedInputStream=new BufferedInputStream(windowStream);
byte[] contents = new byte[1024];
System.out.println("WINDOWLOG NAME"+zipEntry.getName());
int bytesRead = 0;
while((bytesRead = bufferedInputStream.read(contents)) != -1) {
strWindowLogFileContents += new String(contents, 0, bytesRead);
}
}
}
zis.closeEntry();
zipEntry = zis.getNextEntry();
}
errorString[0]=strErrorLogFileContents;
errorString[1]=strWindowLogFileContents;
zis.closeEntry();
zis.close();
System.out.println("Buffers ready");
return errorString;
}
Items accessed inside the parent zip folder (my console output):
unzippingC:logFolders/logX3.zip/logX3/
unzippingC:logFolders/logX3.zip/logX3/Anan/
unzippingC:logFolders/logX3.zip/logX3/Anan/errorreports/
unzippingC:logFolders/logX3.zip/logX3/Anan/errorreports/2021-11-23_103518.zip
unzippingC:logFolders/logX3.zip/logX3/Anan/errorreports/errorlog.txt
unzippingC:logX3.zip/logX3/Anan/errorreports/version.txt
unzippingC:logFolders/logX3.zip/logX3/Anan/errorreports/windowlog.txt
As you can see the program only go until 2021-11-23_103518.zip and goes in another path after that but 2021-11-23_103518.zip has children items(files) that I need to access
appreciate any help, thanks
A zip file is not a folder. Although Windows treats a zip file as if it’s a folder,* it is not a folder. A .zip file is a single file with an internal table of entries, each containing compressed data.
Each inner .zip file you read requires a new ZipFile or ZipInputStream. There is no way around that.
You should not create new ZipFile instances to read the same .zip file’s entries. You only need one ZipFile object. You can go through its entries with its entries() method, and you can read each entry with the ZipFile’s getInputStream method.
(I wouldn’t be surprised if using multiple objects to read the same zip file were to run into file locking problems on Windows.)
try (ZipFile zipFile = new ZipFile(path))
{
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements())
{
ZipEntry zipEntry = entries.nextElement();
if (zipEntry.getName().endsWith("errorlog.txt"))
{
try (InputStream errorStream = zipFile.getInputStream(zipEntry))
{
// ...
}
}
}
}
Notice that no other ZipFile or ZipInputStream objects are created. Only zipFile reads and traverses the file. Also notice the use of a try-with-resources statement to implicitly close the ZipFile and the InputStream.
You should not use += to build a String. Doing so creates a lot of intermediate String objects which will have to be garbage collected, which can hurt your program’s performance. You should wrap each zip entry’s InputStream in an InputStreamReader, then use that Reader’s transferTo method to append to a single StringWriter that holds your combined log.
String strErrorLogFileContents = new StringWriter();
String strWindowLogFileContents = new StringWriter();
try (ZipFile zipFile = new ZipFile(path))
{
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements())
{
ZipEntry zipEntry = entries.nextElement();
if (zipEntry.getName().endsWith("errorlog.txt"))
{
try (Reader entryReader = new InputStreamReader(
zipFile.getInputStream(zipEntry),
StandardCharsets.UTF_8))
{
entryReader.transferTo(strErrorLogFileContents);
}
}
}
}
Notice the use of StandardCharsets.UTF_8. It is almost never correct to create a String from bytes without specifying the Charset. If you don’t provide the Charset, Java will use the system’s default Charset, which means your program will behave differently in Windows than it will on other operating systems.
If you are stuck with Java 8, you won’t have the transferTo method of Reader, so you will have to do the work yourself:
if (zipEntry.getName().endsWith("errorlog.txt"))
{
try (Reader entryReader = new BufferedReader(
new InputStreamReader(
zipFile.getInputStream(zipEntry),
StandardCharsets.UTF_8)))
{
int c;
while ((c = entryReader.read()) >= 0)
{
strErrorLogFileContents.write(c);
}
}
}
The use of BufferedReader means you don’t need to create your own array and implement bulk reads yourself. BufferedReader already does that for you.
As mentioned above, a zip entry which is itself an inner zip file requires a brand new ZipFile or ZipInputStream object to read it. I recommend copying the entry to a temporary file, since reading from a ZipInputStream made from another ZipInputStream is known to be slow, then deleting the temporary file after you’re done reading it.
try (ZipFile zipFile = new ZipFile(path))
{
Enumeration<? extends ZipEntry> entries = zipFile.entries();
while (entries.hasMoreElements())
{
ZipEntry zipEntry = entries.nextElement();
if (zipEntry.getName().endsWith(".zip"))
{
Path tempZipFile = Files.createTempFile(null, ".zip");
try (InputStream errorStream = zipFile.getInputStream(zipEntry))
{
Files.copy(errorStream, tempZipFile,
StandardCopyOption.REPLACE_EXISTING);
}
String[] logsFromZip = getLogBuffers(tempZipFile.toString());
strErrorLogFileContents.write(logsFromZip[0]);
strWindowLogFileContents.write(logsFromZip[1]);
Files.delete(tempZipFile);
}
}
}
Finally, consider creating a meaningful class for your return value. An array of Strings is difficult to understand. A caller won’t know that it always contains exactly two elements and won’t know what those two elements are. A custom return type would be pretty short:
public class Logs {
private final String errorLog;
private final String windowLog;
public Logs(String errorLog,
String windowLog)
{
this.errorLog = errorLog;
this.windowLog = windowLog;
}
public String getErrorLog()
{
return errorLog;
}
public String getWindowLog()
{
return windowLog;
}
}
As of Java 16, you can use a record to make the declaration much shorter:
public record Logs(String errorLog,
String windowLog)
{ }
Whether you use a record or write out the class, you can use it as a return type in your method:
public static Logs getLogBuffers(String path) throws IOException
{
// ...
return new Logs(
strErrorLogFileContents.toString(),
strWindowLogFileContents.toString());
}
* The Windows explorer shell’s practice of treating zip files as folders is a pretty bad user interface. I know I’m not the only one who thinks so. It often ends up making things more difficult for users instead of easier.
HI
so my code works like this, I get a docx and a folder to put the unzip files,
String templateLocation = "//path"; //this is where the document is located
String AUX = "//path"; //this is a aux folder that's get the unzip files
unzip(new File(templateLocation), new File(AUX));
and the method unzip is
private static void unzip(File zipfile, File directory) throws IOException {
ZipFile zfile = new ZipFile(zipfile);
Enumeration<? extends ZipEntry> entries = zfile.entries();
while (entries.hasMoreElements()) {
ZipEntry entry = entries.nextElement();
File file = new File(directory, entry.getName());
if (entry.isDirectory()) {
file.mkdirs();
}
else {
file.getParentFile().mkdirs();
InputStream in = zfile.getInputStream(entry);
try {
copy(in, file);
}
finally {
in.close();
}
}
}
}
the thing is that i need to use a external docx that's in Base64
but how?
attempt with this
String wordx = "DocxInBase64";
byte[] dataFileWord = java.util.Base64.getDecoder().decode(wordx);
String dataw = new String(dataFileWord,StandardCharsets.UTF_8);
But im getting something that looks like corrupted
PK����Xs���g����l}'_B�R;�q�u#��.�����~�Hwx�=��4��������pv�{3o�'M,���b���wi�O���0��E]}`�x��?...
any ideas to start with?
Thanks in advance
You can use Apache POI to parse word files.
http://poi.apache.org/document/index.html