How to use java.util.zip for epub - java

I have to edit the html files of epubs programmatically so what I did was to unzip the .epub and create a parser to make the necessary edits for the html files. However, when I convert them back into an .epub using my code, EpubChecker shows that:
Error: Required META-INF/container.xml resource is missing
When I uncompressed my edited .epub, the container.xml is present and is not missing.
I understand that the mimetype and META-INF has to be zipped first. Here is my code to convert the files back to epub:
FileOutputStream fos = new FileOutputStream(zipFile);
ZipOutputStream zos = new ZipOutputStream(fos);
System.out.println("Output to Zip : " + zipFile);
writeMimeType(zos);
ZipEntry container = new ZipEntry("META-INF\\container.xml");
zos.putNextEntry(container);
FileInputStream inMime2 = new FileInputStream(SOURCE_FOLDER + File.separator + "META-INF\\container.xml");
int len2;
while((len2 = inMime2.read(buffer)) > 0){
zos.write(buffer, 0, len2);
}
inMime2.close();
for(String file : this.fileList){
if(!file.toString().equals("mimetype") && !file.toString().equals("META-INF\\container.xml")){
System.out.println("File Added : " + file);
ZipEntry ze= new ZipEntry(file);
zos.putNextEntry(ze);
FileInputStream in =
new FileInputStream(SOURCE_FOLDER + File.separator + file);
int len;
while ((len = in.read(buffer)) > 0) {
zos.write(buffer, 0, len);
}
in.close();
}
}
zos.closeEntry();
zos.close();
When I manually zip the directory using WinRar, no errors are seen and it works properly. I don't know what I am doing wrong. Can somebody please help me?Thank you.

Looks like you're on Windows, so your FileInputStream(SOURCE_FOLDER + File.separator + "META-INF\\container.xml"); statement is correct for the OS, but I'd guess you need to change the other 2 strings to use the forward slash for the zipentry path.
ZipEntry container = new ZipEntry("META-INF\\container.xml");
try instead as
ZipEntry container = new ZipEntry("META-INF/container.xml");
and change
if(!file.toString().equals("mimetype") && !file.toString().equals("META-INF\\container.xml")){
to
if(!file.toString().equals("mimetype") && !file.toString().equals("META-INF/container.xml")){
accordingly.
You may need to adjust your other ZipEntry's as well. From the ZIP spec (section "4.4.17 file name"):
All slashes MUST be forward slashes '/' as opposed to backwards
slashes '\'

Related

java.io.FileNotFoundException: (The system cannot find the path specified) for zipfile in java

Copying the files from subfolder of zipfile to other zipfile subfolder.
Getting File not found exception at ZipInputStream.
I have checked in source path file is exists. Kindly send me whatever i specified in srcFile path.
File srcFile = new File(sourceFile+ File.separator + versions[j]+ File.separator + folders[l]+ File.separator +entryList[3]);
ZipInputStream zis = new ZipInputStream(new FileInputStream(srcFile));
while ((len = zis.read(buffer)) != -1){
zipout.putNextEntry(zEntry);
zipout.write(buffer, 0, len);
}
It is showing the path correctly as D:\LAB\archive\8367.zip\1\2l\FS-restore.txt
but getting exception also.
sourceFile is D:\LAB\archive\8367.zip
versions and folders are subfolders name and entryList is file name.
Resolved error by using new stream with new zipentry. loc_ze = new ZipEntry(zEntry.getName()); zipout.putNextEntry(loc_ze); zipfile = new ZipFile(sourceFile); InputStream stream = zipfile.getInputStream(zEntry); while ((len = stream.read(b)) != -1) { zipout.write(b, 0, len); }

FileNotFoundException from new FileOutputStream

I am trying to make a program that will get all files within a jar file, and then copy them.
This is the code I am using to copying files:
public static void copyFolder(File src, File dest)
throws IOException{
if(src.isDirectory()){
//if directory not exists, create it
if(!dest.exists()){
dest.mkdir();
System.out.println("Directory copied from "
+ src + " to " + dest);
}
//list all the directory contents
String files[] = src.list();
for (String file : files) {
//construct the src and dest file structure
File srcFile = new File(src, file);
File destFile = new File(dest, file);
//recursive copy
copyFolder(srcFile,destFile);
}
}else{
//if file, then copy it
//Use bytes stream to support all file types
InputStream in = new FileInputStream(src);
OutputStream out = new FileOutputStream(dest);
byte[] buffer = new byte[1024];
int length;
//copy the file content in bytes
while ((length = in.read(buffer)) > 0){
out.write(buffer, 0, length);
}
in.close();
out.close();
System.out.println("File copied from " + src + " to " + dest);
}
}
But there is an error - java.io.FileNotFoundException: (Access is denied) in OutputStream out = new FileOutputStream(dest);. Now, I have no idea why or what does that really mean? How can I fix it?
Plus, I have absolutely no idea how to extract files from a jar file. I have seen the ZipFile class but I don't really know how to use it... So that leaves me with 3 questions:
1. Whats wrong with the copying code?
2. What does Access is denied mean?
3. Can anyone give me a method for getting files from a jar file? Because jar.listFiles() returns an empty list.
Thanks in advance!
Can anyone give me a method for getting files from a jar file?
I've written some utility classes to work with JARs/ ZIPs based on the NIO.2 File API (the library is Open Source):
Maven:
<dependency>
<groupId>org.softsmithy.lib</groupId>
<artifactId>softsmithy-lib-core</artifactId>
<version>0.4</version>
</dependency>
Tutorial:
http://softsmithy.sourceforge.net/lib/current/docs/tutorial/nio-file/index.html#ExtractJarResourceSample

How to create ZIP files using list of Input streams?

In my case I have to download images from the resources folder in my web app. Right now I am using the following code to download images through URL.
url = new URL(properties.getOesServerURL() + "//resources//WebFiles//images//" + imgPath);
filename = url.getFile();
is = url.openStream();
os = new FileOutputStream(sClientPhysicalPath + "//resources//WebFiles//images//" + imgPath);
b = new byte[2048];
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
But I want a single operation to read all images at once and create a zip file for this.
I don't know so much about the use of sequence input streams and zip input streams so if it is possible through these, please let me know.
The only way I can see you being able to do this is something like the following:
try {
ZipOutputStream zip = new ZipOutputStream(new FileOutputStream("C:/archive.zip"));
//GetImgURLs() is however you get your image URLs
for(URL imgURL : GetImgURLs()) {
is = imgURL.openStream();
zip.putNextEntry(new ZipEntry(imgURL.getFile()));
int length;
byte[] b = new byte[2048];
while((length = is.read(b)) > 0) {
zip.write(b, 0, length);
}
zip.closeEntry();
is.close();
}
zip.close();
}
Ref: ZipOutputStream Example
The url should return zip file. Else you have to take one by one and create a zip using your program

uncompress files from a tar using apache commons - prob is duplicate entry

Scenario: Uncompress a tar file using Apache commons.
Problem: The tar i am using is a build tar which gets deployed into a web server. This tar contains duplicate entries like below.
appender_class.xml
APPENDER_CLASS.xml
when extracting using the below code only appender_class.xml is extracted but i want both the files how can i do that ? Renaming in fly is fine but how can i accomplish that?
public static void untar(File[] files) throws Exception {
String path = files[0].toString();
File tarPath = new File(path);
TarEntry entry;
TarInputStream inputStream = null;
FileOutputStream outputStream = null;
try {
inputStream = new TarInputStream(new FileInputStream(tarPath));
while (null != (entry = inputStream.getNextEntry())) {
int bytesRead;
System.out.println("tarpath:" + tarPath.getName());
System.out.println("Entry:" + entry.getName());
String pathWithoutName = path.substring(0, path.indexOf(tarPath.getName()));
System.out.println("pathname:" + pathWithoutName);
if (entry.isDirectory()) {
File directory = new File(pathWithoutName + entry.getName());
directory.mkdir();
continue;
}
byte[] buffer = new byte[1024];
outputStream = new FileOutputStream(pathWithoutName + entry.getName());
while ((bytesRead = inputStream.read(buffer, 0, 1024)) > -1) {
outputStream.write(buffer, 0, bytesRead);
}
System.out.println("Extracted " + entry.getName());
}
}
Try opening your FileOutputstream like this instead:
File outputFile = new File(pathWithoutName + entry.getName());
for(int i = 2; outputFile.exists(); i++) {
outputFile = new File(pathWithoutName + entry.getName() + i);
}
outputStream = new FileOutputStream(outputFile);
It should generate a file called APPENDER_CLASS.xml2 if it encounters a previously created file called APPENDER_CLASS.xml. If a APPENDER_CLASS.xml2 exists it will create a APPENDER_CLASS.xml3, ad infinitum.
File.exists() takes case sensitivity into account (windows filenames are case insensitive, whereas unix, linux and mac are case sensitive). Thus with the above code on case insensitive filesystems the file would be renamed and on case sensitive filesystems the file would not be renamed.

Extract a .tar.gz file in java (JSP)

I can't seem to import the packages needed or find any online examples of how to extract a .tar.gz file in java.
What makes it worse is I'm using JSP pages and am having trouble importing packages into my project. I'm copying the .jar's into WebContent/WEB-INF/lib/ and then right clicking on the project and selecting import external jar and importing it. Sometimes the packages resolve, other times they don't. Can't seem to get GZIP to import either. The imports in eclipse for jsp aren't intuitive like they are in normal Java code where you can right click a recognized package and select import.
I've tried the Apache commons library, the ice and another one called JTar. Ice has imported, but I can't find any examples of how to use it?
I guess I need to uncompress the gzipped part first, then open it with the tarstream?
Any help is greatly appreciated.
The accepted answer works fine, but I think it is redundant to have a write to file operation.
You could use something like
TarArchiveInputStream tarInput =
new TarArchiveInputStream(new GZipInputStream(new FileInputStream("Your file name")));
TarArchiveEntry currentEntry = tarInput.getNextTarEntry();
while(currentEntry != null) {
File f = currentEntry.getFile();
// TODO write to file as usual
}
Hope this help.
Maven Repo
Ok, i finally figured this out, here is my code in case this helps anyone in the future.
Its written in Java, using the apache commons io and compress librarys.
File dir = new File("directory/of/.tar.gz/files/here");
File listDir[] = dir.listFiles();
if (listDir.length!=0){
for (File i:listDir){
/* Warning! this will try and extract all files in the directory
if other files exist, a for loop needs to go here to check that
the file (i) is an archive file before proceeding */
if (i.isDirectory()){
break;
}
String fileName = i.toString();
String tarFileName = fileName +".tar";
FileInputStream instream= new FileInputStream(fileName);
GZIPInputStream ginstream =new GZIPInputStream(instream);
FileOutputStream outstream = new FileOutputStream(tarFileName);
byte[] buf = new byte[1024];
int len;
while ((len = ginstream.read(buf)) > 0)
{
outstream.write(buf, 0, len);
}
ginstream.close();
outstream.close();
//There should now be tar files in the directory
//extract specific files from tar
TarArchiveInputStream myTarFile=new TarArchiveInputStream(new FileInputStream(tarFileName));
TarArchiveEntry entry = null;
int offset;
FileOutputStream outputFile=null;
//read every single entry in TAR file
while ((entry = myTarFile.getNextTarEntry()) != null) {
//the following two lines remove the .tar.gz extension for the folder name
String fileName = i.getName().substring(0, i.getName().lastIndexOf('.'));
fileName = fileName.substring(0, fileName.lastIndexOf('.'));
File outputDir = new File(i.getParent() + "/" + fileName + "/" + entry.getName());
if(! outputDir.getParentFile().exists()){
outputDir.getParentFile().mkdirs();
}
//if the entry in the tar is a directory, it needs to be created, only files can be extracted
if(entry.isDirectory){
outputDir.mkdirs();
}else{
byte[] content = new byte[(int) entry.getSize()];
offset=0;
myTarFile.read(content, offset, content.length - offset);
outputFile=new FileOutputStream(outputDir);
IOUtils.write(content,outputFile);
outputFile.close();
}
}
//close and delete the tar files, leaving the original .tar.gz and the extracted folders
myTarFile.close();
File tarFile = new File(tarFileName);
tarFile.delete();
}
}

Categories

Resources