| By Alexandre Lemieux | Article Rating: |
|
| February 1, 2000 12:00 AM EST | Reads: |
8,453 |
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:
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:
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();
}
public int read(byte[] b, int off, int len)
int read = internalInputStream.read(b,off,len);
throws IOException {
if (startTime == -1)
startTime = System.currentTimeMillis();
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.
Published February 1, 2000 Reads 8,453
Copyright © 2000 SYS-CON Media, Inc. — All Rights Reserved.
Syndicated stories and blog feeds, all rights reserved by the author.
More Stories By 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.
- It's the Java vs. C++ Shootout Revisited!
- Patterns for Building High Performance Applications
- OpenXava 4.3: Rapid Java Web Development
- Asynchronous Logging Using Spring
- Java for Programmers (2nd Edition)
- Cross-Platform Mobile Website Development – a Tool Comparison
- Write Once Run Anywhere or Cross Platform Mobile Development Tools
- Three Buzzwords That Every CIO Hears but One They Should Listen To
- Immersing into JavaScript Frameworks
- Workday Reportedly Prepping to Go Public
- Book Review: Sams Teach Yourself Java in 24 Hours
- Cloud Expo New York: The Java EE 7 Platform - Developing for the Cloud
- Book Excerpt: Introducing HTML5
- Adobe Sends Flex to the Apache Foundation
- Five Years Waiting for JRE 7: Is It Justified? (Part 1)
- Book Excerpt: Java Application Profiling Tips and Tricks
- i-Technology in 2012: Five Industry Predictions
- It's the Java vs. C++ Shootout Revisited!
- Patterns for Building High Performance Applications
- OpenXava 4.3: Rapid Java Web Development
- The Next Web Architecture
- Asynchronous Logging Using Spring
- Java for Programmers (2nd Edition)
- Is Write Once Run Anywhere Ever Going to Be a Reality?
- A Cup of AJAX? Nay, Just Regular Java Please
- Java Developer's Journal Exclusive: 2006 "JDJ Editors' Choice" Awards
- JavaServer Faces (JSF) vs Struts
- The i-Technology Right Stuff
- Rich Internet Applications with Adobe Flex 2 and Java
- Java vs C++ "Shootout" Revisited
- Bean-Managed Persistence Using a Proxy List
- Reporting Made Easy with JasperReports and Hibernate
- Creating a Pet Store Application with JavaServer Faces, Spring, and Hibernate
- Why Do 'Cool Kids' Choose Ruby or PHP to Build Websites Instead of Java?
- What's New in Eclipse?
- i-Technology Predictions for 2007: Where's It All Headed?
















