Digital Edition

SYS-CON.TV
What's Going On with Your Downloads?
What's Going On with Your Downloads?

With the Internet widely available, many software clients are asking for built-in networking capabilities. Data exchange is an advantage in any software product, and software that offers networking functions has a better chance of being selected.

Although the Internet has spread throughout the world, the rate of data transmission is still a problem, even on your business's local area network. Getting files from the Internet easily takes a few minutes even with a high-speed connection. Users want to see what's going on with their software when it's looking for data on the Internet. Telling them when it's over isn't sufficient. Programmers need to show them, by any means possible, that data is flowing between the server and their software. Elements such as the completion percentage, transfer rate, progress bar, estimated remaining download time and animation will make users wait more patiently in front of their screen. No more "Please wait..." messages.

I'll propose two classes that'll enable you to provide the details your clients are asking for. Your data transfer won't be faster, but users will be more likely to wait until the end rather than click the "Cancel" button in desperation.

I/O Handling
Before going into implementation details, I'll do a brief overview of I/O handling in Java. As you probably know, there are two I/O families: the input and output streams and the reader/writers.

Streams are low-level classes that allow you to directly use the disk, networking and peripherals to read and write raw bytes. Readers and writers are wrapper classes that translate unformatted data provided by the streams in data types, thus allowing them to be handled by programmers (boolean, int, float, string, even serialized objects). Since I'm willing to provide a source-dependent solution, I'd implement streams as base classes rather than readers and writers because they're too specific to be used in this situation.

There are more than 20 classes for handling data I/O in the stream mode, but they all have something in common: they inherit from the java.io.InputStream or java.io.OutputStream classes. Studying these classes, I've found that only two of their methods are abstract: the read() method (from the InputStream) and the write() method (from the OutputStream). All I had to do was implement these methods and add new ones.

The Architecture Used
I'll create wrapper classes that will plug into other classes to add functions to the old ones, the same way reader and writer classes do. See Figure 1 for the class hierarchy diagram.

Defining the Problem
Which variables should you show to your users to make their wait a little easier? Here's a short list of data users want to see:

  • Number of bytes read
  • Total size
  • Elapsed downloading or uploading time
  • Mean transfer rate
  • Estimated remaining download or upload time

    To provide your users with this data, you need only a few variables - start time, number of bytes read and total size. With these variables you'll be able to compute any of the values listed above. It must be said, however, that some of these variables aren't always available. While downloading data from a servlet, for example, you won't know the full length of what you're downloading until it's over (and that's too late). This is also the case for most custom protocols over a socket connection.

    Implementing the Classes
    Since these classes must be able to be used from any source, they must inherit from java.io.InputStream and java.io.OutputStream. As I've said before, it's impossible to know the exact length of an InputStream or an OutputStream. This leaves us with two possibilities: force the developer to give it through a constructor, which allows us to provide needed values, or simply ignore it, in which case some values won't be available. The only exception to this problem is the java.net.URL object. With the java.net.URLConnection class, the developer will usually know the size of a download before reading it. To simplify the process, a special constructor has been made to handle URLs.

    Here are the constructors for both wrapper classes:

  • DownloadInputStream(InputStream is, int size)
  • DownloadInputStream(InputStream is)
  • DownloadInputStream(URL url)
  • UploadOutputStream(OutputStream os, int size)
  • UploadOutputStream(OutputStream os)

    Almost every method call is simply a call to its equivalent on the private internal instance. The available() method of DownloadInputStream calls the available() method on the private instance of the InputStream given through the constructor.

    public int available() throws IOException {
    return internalInputStream.available();
    }

    You need to know the starting time and the number of bytes being read up to now. To provide the user with this data, you need to reimplement the read(...) and write(...) methods so that the information is computed as the stream is being used. The following code shows the reimplementation of the read(...) method of the DownloadInputStream.

    public int read(byte[] b, int off, int len)
    throws IOException {
    if (startTime == -1)
    startTime = System.currentTimeMillis();

    int read = internalInputStream.read(b,off,len);
    bytesRead += read;
    return read;
    }

    All you have to do is implement new methods that'll compute all the information you need to know about these streams with the new variables.

    The transfer rate is quite simple - divide the number of bytes being read by the elapsed download time. The result is in bytes per millisecond. See Listing 1 for the exact implementation of this method.

    The estimated remaining download or upload time is computed with an interpolation that relies on the transfer rate you've just computed. The hypothesis is that the rest of the data to be transferred will be downloaded/uploaded at approximately the same rate as the first part. The -1 value is returned if the full length of the input or output stream is unknown. The exact implementation of this method is shown in Listing 2.

    Example
    Finally, since a bit of code is worth a thousand words, I've provided an example to prove how simple it can be to use these classes. It's a short program that downloads a given file from a URL on the local disk. While the file is being downloaded, data such as transfer rate, estimated remaining download time and a progress bar will show the user the state of his or her download (see Figure 3). See Listing 3 for the full example code.

    Limitations
    Keep in mind that the data provided by these classes must be carefully interpreted. If you build a program that calls the read(...) method every five minutes, you won't get the exact transfer rate and estimated download time whether you're using a 100Mb LAN or a dial-up modem. Since the interpolation is really simple, it can't handle extreme cases such as this.

    With this in mind, you'll now be able to use these classes to provide your users with all the data they want to know. Since these classes can be used with the same methods as the common Java Input and Output Streams, you won't have to go through a learning curve.

    About Alexandre Lemieux
    Alexandre Lemieux is studying computer
    engineering at the
    Universite du Quebec ˆ Chicoutimi in Canada. He also teaches UNIX, PERL and Java at the Humanis, Centre de Formation
    Continue, and manages a software development project for Humanis using Java servlets and
    distributed objects
    with RMI.

  • In order to post a comment you need to be registered and logged in.

    Register | Sign-in

    Reader Feedback: Page 1 of 1



    ADS BY GOOGLE
    Subscribe to the World's Most Powerful Newsletters

    ADS BY GOOGLE

    For better or worse, DevOps has gone mainstream. All doubt was removed when IBM and HP threw up thei...
    "We are a well-established player in the application life cycle management market and we also have a...
    Historically, some banking activities such as trading have been relying heavily on analytics and cut...
    In his session at 20th Cloud Expo, Scott Davis, CTO of Embotics, discussed how automation can provid...
    Given the popularity of the containers, further investment in the telco/cable industry is needed to ...
    Your homes and cars can be automated and self-serviced. Why can't your storage? From simply asking q...
    Containers are rapidly finding their way into enterprise data centers, but change is difficult. How ...
    Companies are harnessing data in ways we once associated with science fiction. Analysts have access ...
    Learn how to solve the problem of keeping files in sync between multiple Docker containers. In his ...
    "This week we're really focusing on scalability, asset preservation and how do you back up to the cl...
    Enterprise architects are increasingly adopting multi-cloud strategies as they seek to utilize exist...
    Docker containers have brought great opportunities to shorten the deployment process through continu...
    Kubernetes is a new and revolutionary open-sourced system for managing containers across multiple ho...
    Leading companies, from the Global Fortune 500 to the smallest companies, are adopting hybrid cloud ...
    "We work around really protecting the confidentiality of information, and by doing so we've develope...
    In his session at Cloud Expo, Alan Winters, U.S. Head of Business Development at MobiDev, presented ...
    In his keynote at 19th Cloud Expo, Sheng Liang, co-founder and CEO of Rancher Labs, discussed the te...
    In IT, we sometimes coin terms for things before we know exactly what they are and how they’ll be us...
    Data is the fuel that drives the machine learning algorithmic engines and ultimately provides the bu...
    When shopping for a new data processing platform for IoT solutions, many development teams want to b...