Hello world example on VFS: create a zip file from scratch - java

I would like to create a zip file with Commons VFS2 library. I know how to copy a file when using file prefix but for zip files write and read are not implemented.
fileSystemManager.resolveFile("path comes here")-method fails when I try path zip:/some/file.zip when file.zip is an non-existing zip-file. I can resolve an existing file but non-existing new file fails.
So how to create that new zip file then? I cannot use createFile() because it is not supported and I cannot create the FileObject before this is to be called.
The normal way is to create FileObject with that resolveFile and then call createFile for the object.

The answer to my need is the following code snippet:
// Create access to zip.
FileSystemManager fsManager = VFS.getManager();
FileObject zipFile = fsManager.resolveFile("file:/path/to/the/file.zip");
zipFile.createFile();
ZipOutputStream zos = new ZipOutputStream(zipFile.getContent().getOutputStream());
// add entry/-ies.
ZipEntry zipEntry = new ZipEntry("name_inside_zip");
FileObject entryFile = fsManager.resolveFile("file:/path/to/the/sourcefile.txt");
InputStream is = entryFile.getContent().getInputStream();
// Write to zip.
byte[] buf = new byte[1024];
zos.putNextEntry(zipEntry);
for (int readNum; (readNum = is.read(buf)) != -1;) {
zos.write(buf, 0, readNum);
}
After this you need to close the streams and it works!

In fact, it is possible to create zip files uniquely from Commons-VFS by using the following idio :
destinationFile = fileSystemManager.resolveFile(zipFileName);
// destination is created as a folder, as the inner content of the zip
// is, in fact, a "virtual" folder
destinationFile.createFolder();
// then add files to that "folder" (which is in fact a file)
// and finally close that folder to have a usable zip
destinationFile.close();
// Exception handling is left at user discretion

Related

SevenZFile - Apache Commons Compress 1.15, Uncompress

While Uncompressing .7z file, Empty folders are ignored, I want to consider Empty folders as well after uncompressing any .7z file.
My Code is as below
SevenZFile sevenZFile = new SevenZFile(new File(filename));
SevenZArchiveEntry entry;
while ((entry = sevenZFile.getNextEntry()) != null){
if (entry.isDirectory()){
continue;
}
File curfile = new File(DestinationPath,entry.getName());
File parent = curfile.getParentFile();
if (!parent.exists()) {
parent.mkdirs();
}
FileOutputStream out = new FileOutputStream(curfile);
byte[] content = new byte[(int) entry.getSize()];
sevenZFile.read(content, 0, content.length);
out.write(content);
out.close();
Your code seems working.
Probably the folder aren't in the "yourfile.7zip" from the beginning.
This is a common issue of 7zip and you have to update your 7zip version.
If the 7Zip contains proper arguments just use:
if (entry.isDirectory()){
new File(DestinationPath,entry.getName()).mkdir();
continue;
}
Since:
A file output stream is an output stream for writing data to a File or
to a FileDescriptor.
That is the proper method to accomplish the task because there's no folder implementation by native library vendor.

Replacing a Zip file without unzipping in Java

I have a zip file and I want to replace one file inside it with another file. So do not need to delete a zip entry just replace the file for the zip entry with another.
Here is what I have tried.
public void replaceConfigurationFile(ZipFile zipFile, ZipOutputStream zos, String pathToNewFile, String configFileToReplaced)
throws IOException {
String zipEntryName;
for(Enumeration<?> e = zipFile.entries(); e.hasMoreElements(); ) {
ZipEntry entryIn = (ZipEntry) e.nextElement();
zipEntryName = entryIn.getName();
if(zipEntryName.endsWith(configFileToReplaced)) {
FileInputStream fis = new FileInputStream(pathToNewFile);
ZipEntry zipEntry = new ZipEntry(zipEntryName);
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();
} else {
zos.putNextEntry(entryIn);
InputStream is = zipFile.getInputStream(entryIn);
byte [] buf = new byte[1024];
int len;
while((len = (is.read(buf))) > 0) {
zos.write(buf, 0, len);
}
zos.closeEntry();
}
} // enf of for
}
I have a file zip Entry named :
WEB-INF/classes/config/app-dev.yml
and I have a file at location d drive at location
D:/app-dev.yml
I am able to copy the file in to a different zip file by replacing the file i want to replace . But that is really not needed (to create a different file).
So what should I do to just replace the file with my custom file.
I have searched different posts in Stackoverflow, but unable to find what i need. I read that zip entry cannot be deleted but what about replacing it ? Please help
Your problem is that the new file might be larger than the old file - or smaller! You need to do exactly what you did to allow for the change. The probability that the new file, ZIPped, is exactly the same size as the previous one is virtually nil.
The standard Java ZIP file libraries do not allow you to update an existing ZIP file. You need to use a third party library. A Google search should find you a number of alternatives.
But you need to be aware of a couple of things:
If your application ... or system ... crashes while updating the ZIP file, the file may be corrupted.
When a ZIP file is updated, the replacement version of the file will be appended to the ZIP. The old version of the will still be in the ZIP ... but not in the ZIP file index. Hence updating a ZIP file (without rewriting it) wastes disk space.

Extract files from *.gz extension

I have successfully extracted *.gz from *.tgz and now I have no idea how to actually extract final files from *.tgz.
There are some options using custom packages but that's not an option for me, I need to use standard Java packages only.
What I tried is using same function that I use for *.tgz for *.gz but it doesn't work.
java.util.zip.ZipException: Not in GZIP format 1.gz
Here is function that is extracting *.tgz files.
public String ExtractFile(String path) {
try {
File newFile = new File(this.getFullPathWithoutExtension(path) + ".gz");
GZIPInputStream gStream;
FileOutputStream outStream;
try (FileInputStream fileStream = new FileInputStream(path)) {
gStream = new GZIPInputStream(fileStream);
outStream = new FileOutputStream(newFile);
byte[] buf = new byte[1024];
int len;
while ((len = gStream.read(buf)) > 0) {
outStream.write(buf, 0, len);
}
}
gStream.close();
outStream.close();
newFile.createNewFile();
return newFile.getPath();
} catch (Exception e) {
System.out.print(e);
}
return null;
}
TL;DR; *.tgz files extracted to *.gz files, however *.gz files cannot be extracted.
A .tgz file wouldn't normally be extracted to a .gz file - it would be extracted to a .tar file. (A .gz file is gzipped; a .tar file is an uncompressed archive containing multiple files; a .tgz is a .tar file that's then been gzipped - you've already "undone" the gzipping.)
I don't think there's anything within Java's standard libraries to handle tar files - so you'll either have to revisit your "I can't use anything not in the standard library" decision or reimplement it yourself. The file format is easily available if you decide to do that.

Putting a Folder in a Zip in Java

I am having an issue putting a folder in a zip file I am trying to create. While the path is valid, when I run the code it gives me a File Not Found Exception.
Here is my code
String outFilename = "outfile.zip";
ZipOutputStream out = new ZipOutputStream(new FileOutputStream(outFilename));
byte[] buf = new byte[1024];
File file = new File("workspace");
System.out.println(file.isDirectory());
System.out.println(file.getAbsolutePath());
FileInputStream in = new FileInputStream(file.getAbsolutePath());
out.putNextEntry(new ZipEntry(file.getAbsolutePath()));
int len;
while ((len = in.read(buf)) > 0) {
out.write(buf, 0, len);
}
out.closeEntry();
in.close();
You're trying to read bytes from a directory; it doesn't work like that. The exception says as much, too.
You need to add the directory, then add each file within the directory. If you use the file path you don't need to add the directory explicitly.
I'd be very wary of using the absolute path as the zip entry; better to use a relative path so you can unzip it anywhere and not risk overwriting something you want.

Create a file object from a resource path to an image in a jar file

I need to create a File object out of a file path to an image that is contained in a jar file after creating a jar file. If tried using:
URL url = getClass().getResource("/resources/images/image.jpg");
File imageFile = new File(url.toURI());
but it doesn't work. Does anyone know of another way to do it?
To create a file on Android from a resource or raw file I do this:
try{
InputStream inputStream = getResources().openRawResource(R.raw.some_file);
File tempFile = File.createTempFile("pre", "suf");
copyFile(inputStream, new FileOutputStream(tempFile));
// Now some_file is tempFile .. do what you like
} catch (IOException e) {
throw new RuntimeException("Can't create temp file ", e);
}
private void copyFile(InputStream in, OutputStream out) throws IOException {
byte[] buffer = new byte[1024];
int read;
while((read = in.read(buffer)) != -1){
out.write(buffer, 0, read);
}
}
Don't forget to close your streams etc
This should work.
String imgName = "/resources/images/image.jpg";
InputStream in = getClass().getResourceAsStream(imgName);
ImageIcon img = new ImageIcon(ImageIO.read(in));
Usually, you can't directly get a java.io.File object, since there is no physical file for an entry within a compressed archive. Either you live with a stream (which is best most in the cases, since every good API can work with streams) or you can create a temporary file:
URL imageResource = getClass().getResource("image.gif");
File imageFile = File.createTempFile(
FilenameUtils.getBaseName(imageResource.getFile()),
FilenameUtils.getExtension(imageResource.getFile()));
IOUtils.copy(imageResource.openStream(),
FileUtils.openOutputStream(imageFile));
You cannot create a File object to a reference inside an archive. If you absolutely need a File object, you will need to extract the file to a temporary location first. On the other hand, most good API's will also take an input stream instead, which you can get for a file in an archive.

Categories