java zip filesystem reading zip entries - java

SO, from what I've gathered, one is supposed to be able to create a filesystem from a zip from java 7 and beyond. I'm trying this, the ultimate goal is to use the File object and access these files, just as if I accessed an unzipped file.
import java.io.File;
import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.nio.file.*;
import java.util.*;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class MainZipTest {
public static void main(String[] args) throws IOException, URISyntaxException {
Map<String, String> env = new HashMap<>();
env.put("read", "true");
File file = new File("C:/pathtoazip/data.zip");
URI uri = file.toURI();
String path = "jar:" + uri;
FileSystem fs = FileSystems.newFileSystem(URI.create(path), env);
for (Path p : fs.getRootDirectories()) {
System.out.println("root" + p);
//says "/"
System.out.println(new File(p.toString()).exists());
for (File f : new File(p.toString()).listFiles())
System.out.println(f.getAbsolutePath());
//lists the contents of my c drive!
}
System.out.println(new File("somefile.txt").exists());
System.out.println(fs.getPath("somefile.txt").toFile().exists());
System.out.println(new File("/somefile.txt").exists());
System.out.println(fs.getPath("/somefile.txt").toFile().exists());
}
}
it all prints "false". What am I doing wrong here? Or am I wrong in my assumption that I can access these files through the File object? If so, how does one access them?

Path was introduced as generalization of File (disk file). A Path can be inside a zip file, an URL, and more.
You can use Files with Path for similar File functionality.
for (Path p : fs.getRootDirectories()) {
System.out.println("root: " + p);
System.out.println(Files.exists(p));
Files.list(p).forEach(f -> System.out.println(f.toAbsolutePath()));
}
Note that a Path, like from a zip will maintain its actual file system view (fs, the zip).
So avoid File.

Related

How to zip a byte array using ZipFileSystem

How to create a zip file with a byte array using ZipFileSystem ?
The example in the Zip File System Provider shows how to zip an existing one, but I don't seem to find a way to create one from in memory byte array.
I didn't realize I was using the same value for the target zip file and the file inside the zip file.
Modifying the original example I have this working:
import java.util.*;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.*;
public class ZipFSPUser {
public static void main(String [] args) throws Throwable {
Map<String, String> env = new HashMap<>();
env.put("create", "true");
// locate file system by using the syntax
// defined in java.net.JarURLConnection
URI uri = URI.create("jar:file:/codeSamples/zipfs/zipfstest.zip");
try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
Path pathInZipfile = zipfs.getPath("/SomeTextFile.txt");
// copy a file into the zip file
Files.write(pathInZipfile, new byte[]{'h', 'i'} );
}
}
}
Now the /codeSamples/zipfs/zipfstest.zip file is created with /SomeTextFile.txt inside and when I unzip it the content is indeed hi

getting resources inside a built application

i want to get files inside a folder when my application is running, so i know that i need to get it as resouce, if i will get it as file, it wont work, so it what i did.
jaxbContext = JAXBContext.newInstance(Catalogo.class);
jaxbUnmarshaller = jaxbContext.createUnmarshaller();
InputStream resourceAsStream = getClass().getClassLoader().getResourceAsStream("catalogos/");
BufferedReader br = new BufferedReader(new InputStreamReader(resourceAsStream));
String line;
try {
while((line = br.readLine()) != null){
InputStream resourceAsStream1 = getClass().getClassLoader().getResourceAsStream("catalogos/"+line);
tempCat = (Catalogo) jaxbUnmarshaller.unmarshal(resourceAsStream1);
if(tempCat != null){
codigoCurso = String.valueOf(tempCat.getCourse().getId());
nomeDoCurso = dados.get(codigoCurso);
anoCatalogo = String.valueOf(tempCat.getAno());
if(nomeDoCurso == null){
dados.put(codigoCurso, tempCat.getCourse().getNome());
}
anos.add(anoCatalogo);
}
}
What i want to do is, get all files inside a folder (/catalogos/) and loop through and unmarshall each to an object so i will be able to access the property i need. So, when i run this with netbeans, works perfectly, but when i build and run the jar, i dont get the same result i've got using netbeans, i mean, the data is not where i expected.
The following example demonstrates how to get files from a directory in current runnable jar file and read these files contents.
Assume you have a NetBeans project with name "FolderTestApp". Do the following steps:
In your project root folder FolderTestApp\ create folder myFiles.
Copy your catalogos folder to the FolderTestApp\myFiles\
myFiles folder is necessary to preserve catalogos folder in your jar file structure when project jar is being generated. myFiles folder will disappear from jar file, but catalogos folder will remain.
If you don't do these steps, and place catalogos directly to the project folder (not as a child folder for myFiles), then your files from catalogos folder will be placed to the root of your jar file.
Add myFiles folder as a source folder in netbeans project properties.
Assume your property files contain the following contents:
file1.properties:
key11=value11
key12=value12
key13=value13
file2.properties:
key21=value21
key22=value22
key23=value23
Please note, that code below is not optimized. It is plain'n'dirty proof of concept to show, how to solve your task.
Add the following class to your project:
package folderapp;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.URISyntaxException;
import java.util.Properties;
import java.util.Set;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class FolderTestApp {
public static void main(String[] args) throws URISyntaxException, IOException {
new FolderTestApp();
}
public FolderTestApp() throws URISyntaxException, IOException {
// determining the running jar file location
String jarFilePath = getClass().getProtectionDomain().
getCodeSource().getLocation().toURI().getPath();
// note, that the starting / is removed
// because zip entries won't start with this symbol
String zipEntryFolder = "catalogos/";
try (ZipInputStream zipInputStream
= new ZipInputStream(new FileInputStream(jarFilePath))) {
ZipEntry zipEntry = zipInputStream.getNextEntry();
while (zipEntry != null) {
System.out.println("processing: " + zipEntry.getName());
if (zipEntry.getName().startsWith(zipEntryFolder)) {
// directory "catalogos" will appear as a zip-entry
// and we're checking this condition
if (!zipEntry.isDirectory()) {
// adding symbol / because it is required for getResourceAsStream() call
printProperties("/" + zipEntry.getName());
}
}
zipEntry = zipInputStream.getNextEntry();
}
}
}
public void printProperties(String path) throws IOException {
try (InputStream is = getClass().getResourceAsStream(path)) {
InputStreamReader fr = new InputStreamReader(is);
BufferedReader br = new BufferedReader(fr);
Properties properties = new Properties();
properties.load(br);
System.out.println("contents from: " + path + "\n");
Set<Object> keySet = properties.keySet();
for (Object key : keySet) {
System.out.println(key + " = " + properties.get(key));
}
System.out.println("---------------------------------------");
}
}
}
Set this class as the main class in your project settings (Run section).
And build your project via menu: Run - Build.
As your project has been built, open FolderTestApp/dist folder, where your generated jar is located and run this jar file:
That's it :)

Create a new file in .zip folder using Scala

I have a requirement where I have to create 1 xml file inside my .zip folder.
Can you please let me know how can I achieve this using java/scala?
Also let me know can I directly update .zip folder Array[Byte] and add extra Array[Byte] for my new xml file ?
If you are using Java 7 and later, then you should use Zip File System
The following code sample shows how to create a zip file system and
copy a file to the new zip file system.
import java.util.*;
import java.net.URI;
import java.nio.file.Path;
import java.nio.file.*;
public class ZipFSPUser {
public static void main(String [] args) throws Throwable {
Map<String, String> env = new HashMap<>();
env.put("create", "true");
// locate file system by using the syntax
// defined in java.net.JarURLConnection
URI uri = URI.create("jar:file:/codeSamples/zipfs/zipfstest.zip");
try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
Path externalTxtFile = Paths.get("/codeSamples/zipfs/SomeTextFile.txt");
Path pathInZipfile = zipfs.getPath("/SomeTextFile.txt");
// copy a file into the zip file
Files.copy( externalTxtFile,pathInZipfile,
StandardCopyOption.REPLACE_EXISTING );
}
}
}
This post could help you: Appending files to a zip file with Java

Can a Jar File be updated programmatically without rewriting the whole file?

It is possible to update individual files in a JAR file using the jar command as follows:
jar uf TicTacToe.jar images/new.gif
Is there a way to do this programmatically?
I have to rewrite the entire jar file if I use JarOutputStream, so I was wondering if there was a similar "random access" way to do this. Given that it can be done using the jar tool, I had expected there to be a similar way to do it programmatically.
It is possible to update just parts of the JAR file using Zip File System Provider available in Java 7:
import java.net.URI;
import java.nio.file.FileSystem;
import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardCopyOption;
import java.util.HashMap;
import java.util.Map;
public class ZipFSPUser {
public static void main(String [] args) throws Throwable {
Map<String, String> env = new HashMap<>();
env.put("create", "true");
// locate file system by using the syntax
// defined in java.net.JarURLConnection
URI uri = URI.create("jar:file:/codeSamples/zipfs/zipfstest.zip");
try (FileSystem zipfs = FileSystems.newFileSystem(uri, env)) {
Path externalTxtFile = Paths.get("/codeSamples/zipfs/SomeTextFile.txt");
Path pathInZipfile = zipfs.getPath("/SomeTextFile.txt");
// copy a file into the zip file
Files.copy( externalTxtFile,pathInZipfile,
StandardCopyOption.REPLACE_EXISTING );
}
}
}
Yes, if you use this opensource library you can modify it in this way as well.
https://truevfs.java.net
public static void main(String args[]) throws IOException{
File entry = new TFile("c:/tru6413/server/lib/nxps.jar/dir/second.txt");
Writer writer = new TFileWriter(entry);
try {
writer.write(" this is writing into a file inside an archive");
} finally {
writer.close();
}
}

Moving large files in java

I have to move files from one directory to other directory.
Am using property file. So the source and destination path is stored in property file.
Am haivng property reader class also.
In my source directory am having lots of files. One file should move to other directory if its complete the operation.
File size is more than 500MB.
import java.io.File;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import static java.nio.file.StandardCopyOption.*;
public class Main1
{
public static String primarydir="";
public static String secondarydir="";
public static void main(String[] argv)
throws Exception
{
primarydir=PropertyReader.getProperty("primarydir");
System.out.println(primarydir);
secondarydir=PropertyReader.getProperty("secondarydir");
File dir = new File(primarydir);
secondarydir=PropertyReader.getProperty("secondarydir");
String[] children = dir.list();
if (children == null)
{
System.out.println("does not exist or is not a directory");
}
else
{
for (int i = 0; i < children.length; i++)
{
String filename = children[i];
System.out.println(filename);
try
{
File oldFile = new File(primarydir,children[i]);
System.out.println( "Before Moving"+oldFile.getName());
if (oldFile.renameTo(new File(secondarydir+oldFile.getName())))
{
System.out.println("The file was moved successfully to the new folder");
}
else
{
System.out.println("The File was not moved.");
}
}
catch (Exception e)
{
e.printStackTrace();
}
}
System.out.println("ok");
}
}
}
My code is not moving the file into the correct path.
This is my property file
primarydir=C:/Desktop/A
secondarydir=D:/B
enter code here
Files should be in B drive. How to do? Any one can help me..!!
Change this:
oldFile.renameTo(new File(secondarydir+oldFile.getName()))
To this:
oldFile.renameTo(new File(secondarydir, oldFile.getName()))
It's best not to use string concatenation to join path segments, as the proper way to do it may be platform-dependent.
Edit: If you can use JDK 1.7 APIs, you can use Files.move() instead of File.renameTo()
Code - a java method:
/**
* copy by transfer, use this for cross partition copy,
* #param sFile source file,
* #param tFile target file,
* #throws IOException
*/
public static void copyByTransfer(File sFile, File tFile) throws IOException {
FileInputStream fInput = new FileInputStream(sFile);
FileOutputStream fOutput = new FileOutputStream(tFile);
FileChannel fReadChannel = fInput.getChannel();
FileChannel fWriteChannel = fOutput.getChannel();
fReadChannel.transferTo(0, fReadChannel.size(), fWriteChannel);
fReadChannel.close();
fWriteChannel.close();
fInput.close();
fOutput.close();
}
The method use nio, it make use os underling operation to improve performance.
Here is the import code:
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
If you are in eclipse, just use ctrl + shift + o.

Categories