2

I am running a java application from a jar file. How can I get the size of that file?

Also, how can I get the size of a file from the internet without actually downloading it?

Eventually, I am just going to download the files if they are different sizes, i.e. creating an auto update.

Also, how would this work in the IDE where there is no jar file?

Edit: I need to read a remote file's size anyway for other reasons, so would be nice to know even if it is not the best way.

user3731979
  • 73
  • 3
  • 11
  • 2
    Using file size is an unreliable way to distinguish files; use a hash such as SHA-512 instead. – chrylis -cautiouslyoptimistic- Jun 14 '14 at 21:55
  • @chrylis Please explain further? – user3731979 Jun 14 '14 at 21:57
  • @user3731979 You can't tell if files are different just by looking at the size. Different files might have the same size. Create a Hash from the file, compare it with the other file's hash. If they are the same, you have the same file (don't need to update) if not, download the update. – markhc Jun 14 '14 at 22:19

3 Answers3

3

You could read out the content length after opening the connection (I'm sorry the code is in Scala, but you should get the idea):

scala> import java.net._
import java.net._

scala> val url = new URL("http://repo1.maven.org/maven2/com/typesafe/akka/akka-actor_2.11/2.3.3/akka-actor_2.11-2.3.3.jar")
url: java.net.URL = http://repo1.maven.org/maven2/com/typesafe/akka/akka-actor_2.11/2.3.3/akka-actor_2.11-2.3.3.jar

scala> val httpConnection = url.openConnection()
httpConnection: java.net.URLConnection = sun.net.www.protocol.http.HttpURLConnection:http://repo1.maven.org/maven2/com/typesafe/akka/akka-actor_2.11/2.3.3/akka-actor_2.11-2.3.3.jar

scala> httpConnection.getContentLengthLong
res0: Long = 2514991
Christian
  • 4,543
  • 1
  • 22
  • 31
1

It seems your real goal is to create an auto-updating application. Every Java SE installation comes with Java Web Start, which automatically handles this, including checking your application .jar file's date and downloading it if necessary.

To turn your application into a Java Web Start application is easy. Your code doesn't need to change at all. The web server which hosts your .jar file should also host a short XML file with a .jnlp extension. That file tells Java the .jar file's location, the application's full name, and the minimum version of Java needed to run the application. It can do many other things, including installing itself into the user's Start menu (or the equivalent in Linux and OS X). All of these things are automatically handled when a user elects to run your application, which they do by simply clicking on a hyperlink to your .jnlp file.

The Java Web Start tutorial is here.

A basic .jnlp file might look like this:

<?xml version="1.0"?>
<!DOCTYPE jnlp PUBLIC "-//Sun Microsystems, Inc//DTD JNLP Descriptor 6.0.10//EN" "http://java.sun.com/dtd/JNLP-6.0.10.dtd">
<jnlp version="1.6"
      codebase="http://www.example.com/myapp/"
      href="MyApp.jnlp">

    <information>
        <title>MyApp</title>
        <vendor>ExampleCo Inc.</vendor>
        <homepage href="http://www.example.com/myapp/index.html"/>
        <description>The greatest application ever.</description>
        <icon kind="default" href="myapp48x48.gif"/>
        <offline-allowed/>
    </information>

    <security>
        <all-permissions/>
    </security>

    <resources>
        <j2se version="1.7+"/>
        <jar href="MyApp.jar" main="true"/>
    </resources>

    <application-desc/>
</jnlp>

To address your original question: Java Web Start seems to decide whether to update a file based on the file's server timestamp, much like web browsers do, so if I were going to do it manually (which I wouldn't, because Java Web Start does it much better), I'd use an HTTP HEAD request to read the headers without downloading the file:

boolean isDownloadNeeded(URL url,
                         Path cachedFile)
throws IOException {

    if (Files.notExists(cachedFile)) {
        return true;
    }

    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("HEAD");
    long serverTimestamp = conn.getLastModified();

    long fileTimestamp = Files.getLastModifiedTime(cachedFile).toMillis();

    return (serverTimestamp == 0 || fileTimestamp < serverTimestamp);
}
VGR
  • 40,506
  • 4
  • 48
  • 63
  • Eh, so how do I use this java web start? All I see at the moment is complicated stuff that I don't understand and no code examples. Thanks! – user3731979 Jun 15 '14 at 08:46
  • There are no code examples because you don't need to write any code. Just place a .jnlp file in the same directory as your .jar file on the web server. – VGR Jun 15 '14 at 14:20
  • Wait what? o.O I am confused now. – user3731979 Jun 15 '14 at 14:49
1

I am running a java application from a jar file. How can I get the size of that file?

I don't think you can ... reliably1. The closest you can come is:

  1. Find and parse the program's classpath as described here: https://stackoverflow.com/a/17541055/139985

  2. Identify the classpath component that is the JAR file.

  3. Use File.length() on that file.

The problems are that you may not be able to identify the JAR file from the list, and the file may no longer be there ... depending on how you launched the JVM. Furthermore, the technique doesn't work if you dynamically run the application; i.e. using a classloader that your launcher creates on the fly in Java code in the same JVM.

Also, how can I get the size of a file from the internet without actually downloading it?

Once again, there's no totally reliable way1 to do this. You can attempt to extract the "content-length" header from the HTTP response ... before you start reading the response content. The problem is that "content-length" is optional, and there are situations where an HTTP server will not (or even cannot) provide it.

If you know that the server can give you the content length, then sending a HEAD request rather than a GET request will give you just the response header.

Also, how would this work in the IDE where there is no jar file?

I don't think it is practical.

Eventually, I am just going to download the files if they are different sizes, i.e. creating an auto update.

As others have mentioned, Java Web Start is the way to go. Don't attempt to roll your own scheme. For a start Java Web Start deals with a whole bunch of important security related concerns that would be difficult for you to do ... properly.


1 - What I mean is that the Java application has to make assumptions about other things. For instance, assumptions about the application launcher, and the server that is providing the JAR files.

Community
  • 1
  • 1
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216