I'm making a client updater & I'm getting an error in my cmd whilst trying to unzip the file.
What it's supposed to do is:
check if the file exists in the user's home (user.home),
if it doesn't exist in the user's home, check if the file exists in the project's directory,
if it doesn't exist in the project's directory, download the file; if it does, then unzip the file into the user's home.
The error:
Exists in Directory!
file unzip : C:\Users\Ryan T\Desktop\Rezzion Updater\.rezzion.cache\rezzion.cache
java.io.FileNotFoundException: .rezzion.cache\rezzion.cache\Data (The system cannot find the path specified)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(Unknown Source)
at java.io.FileOutputStream.<init>(Unknown Source)
at rezzion.UnZip.unZipIt(UnZip.java:54)
at rezzion.Downloader.<init>(Downloader.java:68)
at rezzion.Downloader.main(Downloader.java:78)
file unzip : C:\Users\Ryan T\Desktop\Rezzion Updater\.rezzion.cache\rezzion.cache\Data
Image of Project Folder:
my Downloader.java (Main Class):
package rezzion;
import java.awt.FlowLayout;
public class Downloader extends JFrame {
private static final long serialVersionUID = 1L;
private static boolean exists = (new File(System.getProperty("user.home") + ".rezzion.cache")).exists();
private static boolean existsinDir = (new File("rezzion.cache.zip")).exists();
private static String site = "https://dl.dropboxusercontent.com/s/yoh4d17gfgnv2od/rezzion.cache.zip?dl=1&token_hash=AAE1qdxL_-2y_arb8MBnk8AHSsuhLH1-lwSiGVc0ayQKXA";
private static String filename = "rezzion.cache.zip";
private static final String INPUT_ZIP_FILE = "rezzion.cache.zip";
private static final String OUTPUT_FOLDER = ".rezzion.cache";
private final int BUFFER = 1024;
public Downloader() {
JFrame frm = new JFrame();
JProgressBar current = new JProgressBar(0, 100);
current.setBounds(35, 68, 326, 30);
current.setValue(0);
current.setStringPainted(true);
frm.setVisible(true);
frm.getContentPane().setLayout(null);
frm.setSize(400, 200);
frm.setDefaultCloseOperation(EXIT_ON_CLOSE);
if (!exists) {
if (!existsinDir) {
frm.getContentPane().add(current);
try {
URL url = new URL(site);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
int filesize = connection.getContentLength();
float totalDataRead = 0;
java.io.BufferedInputStream in = new java.io.BufferedInputStream(connection.getInputStream());
java.io.FileOutputStream fos = new java.io.FileOutputStream(filename);
java.io.BufferedOutputStream bout = new BufferedOutputStream(fos, BUFFER);
byte[] data = new byte[BUFFER];
int i = 0;
while ((i = in.read(data, 0, BUFFER)) >= 0) {
totalDataRead = totalDataRead + i;
bout.write(data, 0, i);
float Percent = (totalDataRead * 100) / filesize;
current.setValue((int) Percent);
if (current.getValue() == 99) {
current.setValue(100);
}
}
bout.close();
in.close();
} catch (Exception e) {
javax.swing.JOptionPane.showConfirmDialog((java.awt.Component) null, e.getMessage(), "Error", javax.swing.JOptionPane.DEFAULT_OPTION);
}
} else {
System.out.println("Exists in Directory!");
UnZip unZip = new UnZip();
unZip.unZipIt(INPUT_ZIP_FILE, OUTPUT_FOLDER);
//TODO: Exists in Directory
}
} else {
System.out.println("Exists in User.Home!");
//TODO: Exists in User.Home
}
}
public static final void main(String[] args) throws Exception {
new Downloader();
}
/**
*
*/
public static void unzipComplete() {
//TODO
System.out.println("unzip Complete!");
}
}
My UnZip.java (Self Explanatory):
package rezzion;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.List;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class UnZip {
List<String> fileList;
private static final String OUTPUT_FOLDER = ".rezzion.cache";
public void unZipIt(String zipFile, String outputFolder) {
byte[] buffer = new byte[1024];
try {
// create output directory is not exists
File folder = new File(System.getProperty("user.home")
+ OUTPUT_FOLDER);
if (!folder.exists()) {
folder.mkdir();
}
// get the zip file content
ZipInputStream zis = new ZipInputStream(
new FileInputStream(zipFile));
// get the zipped file list entry
ZipEntry ze = zis.getNextEntry();
while (ze != null) {
String fileName = ze.getName();
File newFile = new File(outputFolder + File.separator
+ fileName);
System.out.println("file unzip : " + newFile.getAbsoluteFile());
// create all non exists folders
// else you will hit FileNotFoundException for compressed folder
new File(newFile.getParent()).mkdirs();
FileOutputStream fos = new FileOutputStream(newFile);
int len;
while ((len = zis.read(buffer)) > 0) {
fos.write(buffer, 0, len);
}
fos.close();
ze = zis.getNextEntry();
}
zis.closeEntry();
zis.close();
System.out.println("Done");
Downloader.unzipComplete();
} catch (IOException ex) {
ex.printStackTrace();
}
}
}
Sorry for the poor formatting of this post, but if anyone can help I've been reading this error for a bit & looking at exactly what it's telling me to, tried merging the classes & no luck. Thanks to those that are willing to point something out, even if it's obvious & I'm missing it.
Since this is apparently a desktop app., the answer seems obvious to me. For deploying Java desktop apps., the best option is usually to install the app. using Java Web Start. JWS works on Windows, OS X & *nix.
JWS provides many appealing features including, but not limited to, splash screens, desktop integration, file associations, automatic update (including lazy downloads and programmatic control of updates), partitioning of natives & other resource downloads by platform, architecture or locale, configuration of run-time environment (minimum J2SE version, run-time options, RAM etc.), easy management of common resources using extensions..
..is there a way I could just keep this?
No.
Using automatic updates, you would abandon all that and simply let the JWS client handle it.
The 'programmatic control of updates' uses an API only available to apps. launched using JWS, specifically the DownloadServiceListener.
Related
I have some Java code that does this (on a Windows 10 laptop with Windows Defender on):
unzip a .zip file into a folder (using a zip stream)
immediately list the folder's contents (using File#list)
There are ten files in the zip, from 100kB to 40MB. Normally only the first two files are listed -- the other 8 are silently lost. I know they actually make it to the directory because I can see them when I navigate to the directory myself.
I know there are better ways to implement this code, but I'm curious: is this expected? Is "write file into folder" and "file is listed when you list folder contents" not atomic on Windows? Is it a quirk of the underlying file system? Does Windows Defender make the file invisible for some period of time after it's written?
I am not facing the issue you mentioned and my code is able to list all the files correctly:
package com.test;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
public class ZipTest {
private static final int BUFFER_SIZE = 4096;
private static String INPUT_LOCATION = "C:/temp/zip/test.zip";
private static String OUTPUT_LOCATION = "C:/temp/unzip";
public static void main(String[] args) throws IOException {
unzip(INPUT_LOCATION, OUTPUT_LOCATION);
for (String s : new File(OUTPUT_LOCATION).list()) {
System.out.println(s);
}
}
public static void unzip(String zipFilePath, String destDirectory) throws IOException {
File destDir = new File(destDirectory);
if (!destDir.exists()) {
destDir.mkdir();
}
ZipInputStream zipIn = new ZipInputStream(new FileInputStream(zipFilePath));
ZipEntry entry = zipIn.getNextEntry();
while (entry != null) {
String filePath = destDirectory + File.separator + entry.getName();
if (!entry.isDirectory()) {
extractFile(zipIn, filePath);
} else {
File dir = new File(filePath);
dir.mkdir();
}
zipIn.closeEntry();
entry = zipIn.getNextEntry();
}
zipIn.close();
}
private static void extractFile(ZipInputStream zipIn, String filePath) throws IOException {
BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(filePath));
byte[] bytesIn = new byte[BUFFER_SIZE];
int read = 0;
while ((read = zipIn.read(bytesIn)) != -1) {
bos.write(bytesIn, 0, read);
}
bos.close();
}
}
I am trying to extract an archive .tar.gz using java and I am getting Directory error that I do not seem to understand. Please help. I got this sample code from https://forums.oracle.com/forums/thread.jspa?threadID=2065236
package untargz;
import java.io.*;
import com.ice.tar.*;
import javax.activation.*;
import java.util.zip.GZIPInputStream;
/**
*
* #author stanleymungai
*/
public class Untargz {
public static InputStream getInputStream(String tarFileName) throws Exception{
if(tarFileName.substring(tarFileName.lastIndexOf(".") + 1, tarFileName.lastIndexOf(".") + 3).equalsIgnoreCase("gz")){
System.out.println("Creating an GZIPInputStream for the file");
return new GZIPInputStream(new FileInputStream(new File(tarFileName)));
}else{
System.out.println("Creating an InputStream for the file");
return new FileInputStream(new File(tarFileName));
}
}
private static void untar(InputStream in, String untarDir) throws IOException {
System.out.println("Reading TarInputStream... ");
TarInputStream tin = new TarInputStream(in);
TarEntry tarEntry = tin.getNextEntry();
if(new File(untarDir).exists()){
while (tarEntry != null){
File destPath = new File(untarDir + File.separatorChar + tarEntry.getName());
System.out.println("Processing " + destPath.getAbsoluteFile());
if(!tarEntry.isDirectory()){
FileOutputStream fout = new FileOutputStream(destPath);
tin.copyEntryContents(fout);
fout.close();
}else{
destPath.mkdir();
}
tarEntry = tin.getNextEntry();
}
tin.close();
}else{
System.out.println("That destination directory doesn't exist! " + untarDir);
}
}
private void run(){
try {
String strSourceFile = "C:/AskulInstaller/pid.tar.gz";
String strDest = "C:/AskulInstaller/Extracted Files";
InputStream in = getInputStream(strSourceFile);
untar(in, strDest);
}catch(Exception e) {
e.printStackTrace();
System.out.println(e.getMessage());
}
}
public static void main(String[] args) {
new Untargz().run();
}
}
Once I run this piece of code, this is My Output;
Creating an GZIPInputStream for the file
Reading TarInputStream...
That destination directory doesn't exist! C:/AskulInstaller/Extracted Files
BUILD SUCCESSFUL (total time: 0 seconds)
When I Manually Create the destination Directory C:/AskulInstaller/Extracted Files
I get this Error Output;
Creating an GZIPInputStream for the file
Reading TarInputStream...
Processing C:\AskulInstaller\Extracted Files\AskulInstaller\pid\Askul Logs\DbLayer_AskulMain_10_Apr_2013_07_44.log
java.io.FileNotFoundException: C:\AskulInstaller\Extracted Files\AskulInstaller\pid\Askul Logs\DbLayer_AskulMain_10_Apr_2013_07_44.log (The system cannot find the path specified)
C:\AskulInstaller\Extracted Files\AskulInstaller\pid\Askul Logs\DbLayer_AskulMain_10_Apr_2013_07_44.log (The system cannot find the path specified)
at java.io.FileOutputStream.open(Native Method)
at java.io.FileOutputStream.<init>(FileOutputStream.java:212)
at java.io.FileOutputStream.<init>(FileOutputStream.java:165)
at untargz.Untargz.untar(Untargz.java:37)
at untargz.Untargz.run(Untargz.java:55)
at untargz.Untargz.main(Untargz.java:64)
Is there a way I am supposed to place My directories so that the extraction Happens or what exactly is My Mistake?
If the tar file contains an entry for a file foo/bar.txt but doesn't contain a previous directory entry for foo/ then your code will be trying to create a file in a directory that doesn't exist. Try adding
destFile.getParentFile().mkdirs();
just before you create the FileOutputStream.
Alternatively, if you don't mind your code depending on Ant as a library then you can delegate the whole unpacking process to an Ant task rather than doing it by hand. Something like this (not fully tested):
Project p = new Project();
Untar ut = new Untar();
ut.setProject(p);
ut.setSrc(tarFile);
if(tarFile.getName().endsWith(".gz")) {
ut.setCompression((UntarCompressionMethod)EnumeratedAttribute.getInstance(UntarCompressionMethod.class, "gzip"));
}
ut.setDest(destDir);
ut.perform();
I'm programming using the SWT Widget Library for Java in eclipse, and I'm designing a runnable Java application. I've got the application down, I just don't know how to load external .swf files from a folder on "ALL" computers. I can load Images from any computer, because I use the getResourceAsStream line of code. But the "import com.docuverse.swt.flash.FlashPlayer" "loadMovie(arg, arg)" only takes a String.
So I did ClassName.class.getResource("blah.swf").getPath(); which gives you a string, I set it up, and running it on eclipse it can perfectly find the file in the package. When I export it, the runnable Jar I made cannot find the "blah.swf" inside of the .jar file.
So there is my problem, how do I load my .swf files from within the .jar or from an external folder so clients can download along side the .jar executable application, so it can point to those swf files.
Thankyou.
Here is the way I talked about in comments (creating temp file and save flash animation from jar to it)
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.swt.SWT;
import org.eclipse.swt.layout.FillLayout;
import org.eclipse.swt.widgets.Display;
import org.eclipse.swt.widgets.Shell;
import com.docuverse.swt.flash.FlashPlayer;
public class SWTFlashPlayer {
private FlashPlayer player = null;
private final String FLASH_FILE_PATH = "/EdnCateDance.swf";
private final String TMP_FILE_PREFFIX = "tmp_";
private final String TMP_FILE_SUFFIX = ".swf";
private File swfFile = null;
public SWTFlashPlayer() {
final Display display = new Display();
final Shell shell = new Shell(display);
shell.setLayout(new FillLayout());
try {
swfFile = copyFileFromJar(FLASH_FILE_PATH, TMP_FILE_PREFFIX, TMP_FILE_SUFFIX);
} catch (IOException e) {
e.printStackTrace();
return;
}
player = new FlashPlayer(shell, SWT.NONE);
player.loadMovie(0, swfFile.getAbsolutePath());
player.setSize(150, 150);
player.activate();
shell.pack();
shell.open();
while (!shell.isDisposed()) {
if (!display.readAndDispatch())
display.sleep();
}
display.dispose();
}
/**
* Copy file packed inside current jar to temp file
* #param jarPath String - path inside jar
* #param filePreffix String - temp file preffix
* #param fileSuffix - temp file suffix
* #throws IOException - temp file cannot be created or writing somehow fails
*/
private File copyFileFromJar(String jarPath, String filePreffix, String fileSuffix) throws IOException {
File toFile = File.createTempFile(filePreffix, fileSuffix);
// delete file after application finishes
toFile.deleteOnExit();
if(!toFile.canWrite()) throw new IOException("File (" + toFile.getPath() + ") not exists or is not writable!");
FileOutputStream fos = new FileOutputStream(toFile);
InputStream is = this.getClass().getResourceAsStream(jarPath);
if(is == null) throw new IOException("File on jar path could not be located or loaded!");
int read = 0;
byte bytes[] = new byte[1024];
while ((read = is.read(bytes)) != -1) {
fos.write(bytes, 0, read);
}
fos.flush();
fos.close();
return toFile;
}
public static void main(String[] args) {
new SWTFlashPlayer();
}
}
I used the EdnCateDance.swf flash file which is one of the examples in SWT Flash library.
I have a nice java code that unzips a .zip file. But problem with this code is
i need to create target folders(Note:Only folders not file) before running this code.
Otherwise i will get path not found exception.
So This code wont work if zip file content is not known before. so i think this is useless code. Anyone have better logic? or Bellow code need to be edited?
package com.mireader;
import android.os.Environment;
import android.util.Log;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipInputStream;
/**
*
* #author jon
*/
public class Decompress {
private String _zipFile;
private String _location;
public Decompress(String zipFile, String location) {
_zipFile = zipFile;
_location = location;
_dirChecker("");
}
public void unzip() {
try {
FileInputStream fin = new FileInputStream(_zipFile);
ZipInputStream zin = new ZipInputStream(fin);
ZipEntry ze = null;
byte[] buffer = new byte[1024];
int length;
int i=0;
while ((ze = zin.getNextEntry()) != null) {
Log.v("t", ze.toString());
Log.v("Decompress", "Unzipping " + ze.getName());
if(ze.isDirectory()) {
Log.i("my","Comes to if");
_dirChecker(ze.getName());
}
else {
Log.i("my","Comes to else");
FileOutputStream fout = new FileOutputStream(_location + ze.getName());
while ((length = zin.read(buffer))>0) {
fout.write(buffer, 0, length);
}
zin.closeEntry();
fout.close();
}
}
zin.close();
Log.i("My tag","Success");
}catch(Exception e) {
Log.e("Decompress", "unzip", e);
}
}
private void _dirChecker(String dir) {
File f = new File(_location + dir);
if(!f.isDirectory()) {
Log.i("mytag", "Creating new folder");
f.mkdirs();
System.out.print("stp:"+f.getName());
}
}
}
You can avoid the following piece of code
if(ze.isDirectory()) {
Log.i("my","Comes to if");
_dirChecker(ze.getName());
}
and add code similar to the one below in the file creator else part. It worked for me by creating the entire parent folders.
File file = createFile((baseDirectory +"/" + zipFile.getName()));
file.getParentFile().mkdirs();
It doesn't look that wrong, what exactly is your problem?
You create the directories as they appear in the zip file; I usually do it inline, but it's the same. Your code would fail if your zip file not has the directory stubs inside (which could happen with zip creators in the wild), so my unzip code doublechecks the existance of the directory before extracting each file:
if (zEntry.isDirectory()) new File(destDir+zEntry.getName()).mkdirs();
else
{
String dstEntryDir=new File(destDir+zEntry.getName()).getParent()+File.separator;
if (!fileExists(dstEntryDir)) new File(dstEntryDir).mkdirs();
copyStreamToFile(zFile.getInputStream(zEntry),destDir+zEntry.getName());
}
I am executing an exe through my java program. The path is hardcoded in Java.
I have packaged my the exe in the jar.
But am stuck as I have the path name hardcoded in the Java file, so I am not able to execute my jar as a stand alone program.
Any hints for packaging such jar i.e having an exe inside and able to
run it as a stand alone program?
This will extract the .exe to a local file on the local disk. The file will be deleted when the Java program exists.
import java.io.Closeable;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.URI;
import java.net.URISyntaxException;
import java.net.URL;
import java.security.CodeSource;
import java.security.ProtectionDomain;
import java.util.zip.ZipEntry;
import java.util.zip.ZipException;
import java.util.zip.ZipFile;
public class Main
{
public static void main(final String[] args)
throws URISyntaxException,
ZipException,
IOException
{
final URI uri;
final URI exe;
uri = getJarURI();
exe = getFile(uri, "Main.class");
System.out.println(exe);
}
private static URI getJarURI()
throws URISyntaxException
{
final ProtectionDomain domain;
final CodeSource source;
final URL url;
final URI uri;
domain = Main.class.getProtectionDomain();
source = domain.getCodeSource();
url = source.getLocation();
uri = url.toURI();
return (uri);
}
private static URI getFile(final URI where,
final String fileName)
throws ZipException,
IOException
{
final File location;
final URI fileURI;
location = new File(where);
// not in a JAR, just return the path on disk
if(location.isDirectory())
{
fileURI = URI.create(where.toString() + fileName);
}
else
{
final ZipFile zipFile;
zipFile = new ZipFile(location);
try
{
fileURI = extract(zipFile, fileName);
}
finally
{
zipFile.close();
}
}
return (fileURI);
}
private static URI extract(final ZipFile zipFile,
final String fileName)
throws IOException
{
final File tempFile;
final ZipEntry entry;
final InputStream zipStream;
OutputStream fileStream;
tempFile = File.createTempFile(fileName, Long.toString(System.currentTimeMillis()));
tempFile.deleteOnExit();
entry = zipFile.getEntry(fileName);
if(entry == null)
{
throw new FileNotFoundException("cannot find file: " + fileName + " in archive: " + zipFile.getName());
}
zipStream = zipFile.getInputStream(entry);
fileStream = null;
try
{
final byte[] buf;
int i;
fileStream = new FileOutputStream(tempFile);
buf = new byte[1024];
i = 0;
while((i = zipStream.read(buf)) != -1)
{
fileStream.write(buf, 0, i);
}
}
finally
{
close(zipStream);
close(fileStream);
}
return (tempFile.toURI());
}
private static void close(final Closeable stream)
{
if(stream != null)
{
try
{
stream.close();
}
catch(final IOException ex)
{
ex.printStackTrace();
}
}
}
}
The operating system doesn't care or know about .jar file, so you'll have to unpack the .exe file to some temporary location before you execute it.
//gets program.exe from inside the JAR file as an input stream
InputStream is = getClass().getResource("program.exe").openStream();
//sets the output stream to a system folder
OutputStream os = new FileOutputStream("program.exe");
//2048 here is just my preference
byte[] b = new byte[2048];
int length;
while ((length = is.read(b)) != -1) {
os.write(b, 0, length);
}
is.close();
os.close();
Whilst the other users have answered the question correctly, extract and run then cleanup. Another point to consider is going fully native.
You are already using a native binary to achieve a specific task. Why not also create a native installer which will install your application, and install the binary to the OS specific location (Program Files on Win32) and create suitable shortcuts.
This way your application will feel more native and means you don't need to write or manage code to get around this fact. At the moment the Jar looks like a cross platform piece of code (Jar runs anywhere right?) but packs a native binary which will not run everywhere. This feels like a contradiction.
For installers I can recommend Nullsoft Installation System (NSIS) as they have many excellent tutorials and code samples to learn from.
Use
getClass().getResource(what).openStream()
and copy to another file in the disk.
You could write a simple java program to launch the exe using Runtime.exec(). You could then set the "Main-Class" attribute of the jar to be that launcher class. Users could then run your jar and it would run the exe.