Wouter Lievens
Wouter Lievens

Reputation: 4029

Portable way of finding total disk size in Java (pre java 6)

I need to find the total size of a drive in Java 5 (or 1.5, whatever). I know that Java 6 has a new method in java.io.File, but I need it to work in Java 5.

Apache Commons IO has org.apache.commons.io.FileSystemUtils to provide the free disk space, but not the total disk space.

I realize this is OS dependant and will need to depend on messy command line invocation. I'm fine with it working on "most" systems, i.e. windows/linux/macosx. Preferably I'd like to use an existing library rather than write my own variants.

Any thoughts? Thanks.

Upvotes: 3

Views: 2939

Answers (3)

teabot
teabot

Reputation: 15444

Note: This solution is recommended only as a last ditch attempt

I do not know if this exists in any API/library. However, as a last ditch attempt I would probably create an Ant script or use Ant task implementations to execute an OS command appropriate to the platform and then parse the output stream. Why Ant? - because it provides:

  • Good platform identification (see os condition)
  • Platform independent command execution
  • Ability to parse output from command execution programmatically - by writing the output to a property and then accessing this from the Ant project object.

Yes, this is a little messy, but you could execute said target using the Ant API and then wrap it all up with your own interface. This still wouldn't necessarily cover all possible systems - only those that Ant can identify.

Additionally it is still a fair bit of work, you'll need to work out the correct commands and parsing strategies for all of your target platforms.

Again - last ditch attempt - so wait for other answers and continue your search for other libraries and API offerings.

Upvotes: 1

rics
rics

Reputation: 5596

Here at SUN there is a long history of the free disk space problem. They mention JConfig as a possible solution. Unfortunately this library can only be reached at the end of 2009 summer (hopefully) and now it is not clear whether it solves your original problem since documentation and source is not available, but they state that:

It lets you work with files, web browsers, processes, file types, and other system-level items in a much more advanced manner than that provided by the standard Java class libraries. For instance, you can use it to launch web browsers or other external applications instead of using Runtime.exec or solutions that only work on one platform.

So if you are patient and lucky ...

Upvotes: 0

Rich Seller
Rich Seller

Reputation: 84078

Update:

I apologise for misreading the question, I recommend copying the FileSystemUtils approach, but modifying the commands it runs slightly.

In dos you can get the free and total bytes with the fsutil command:

fsutil volume diskfree [drive letter]

on my box this gives the following results:

Total # of free bytes        : 41707524096
Total # of bytes             : 80023715840
Total # of avail free bytes  : 41707524096

On Unix, the command is still "df -k", you're just interested in the "1024-blocks" column to the left of "Free" (example from Wikipedia below). You obviously need to multiply the result by 1024.

Filesystem    1024-blocks      Free %Used    Iused %Iused Mounted on
/dev/hd4            32768     16016   52%     2271    14% /
/dev/hd2          4587520   1889420   59%    37791     4% /usr
/dev/hd9var         65536     12032   82%      518     4% /var
/dev/hd3           819200    637832   23%     1829     1% /tmp
/dev/hd1           524288    395848   25%      421     1% /home
/proc                   -         -    -         -     -  /proc
/dev/hd10opt        65536     26004   61%      654     4% /opt

Assuming you copy FileSystemUtils to implement "totalSpaceKB()" to delegate to an equivalent OS-specific method. The implementation for Windows would be something like this (note the use of "Find" to trim the output from fsutil to just get the total size):

long totalSpaceWindows(String path) throws IOException {
    path = FilenameUtils.normalize(path);
    if (path.length() > 2 && path.charAt(1) == ':') {
        path = path.substring(0, 2); // seems to make it work
    }

    // build and run the 'fsutil' command
    String[] cmdAttribs = new String[] {
            "cmd.exe",
            "/C",
            "fsutil volume diskfree " + path
                    + " | Find \"Total # of bytes\"" };

    // read in the output of the command to an ArrayList
    List lines = performCommand(cmdAttribs, Integer.MAX_VALUE);

    //because we used Find, we expect the first line to be "Total # of bytes",
    //you might want to add some checking to be sure
    if (lines.size() > 0) {
        String line = (String) lines.get(0);
        String bytes = line.split(":")[1].trim();
        return Long.parseLong(bytes);
    }
    // all lines are blank
    throw new IOException(
            "Command line 'fsutil volume diskfree' did not return 
                    + "any info  for path '" + path + "'");
}

The implementation for Unix would be the same as freeSpaceUnix(), but remove the two calls to tok.nextToken() at the end of the method

    /** comment these two lines so the token received is the total size */
    tok.nextToken(); // Ignore 1K-blocks
    tok.nextToken(); // Ignore Used
    /** this will now be the total size */
    String freeSpace = tok.nextToken();
    return parseBytes(freeSpace, path);
}

The implementations for other platforms would be similar.

Hope this helps and apologies agian for misreading the problem.


Original answer (gets free bytes, not total).

Prior to Java 6 there isn't an elegant way to do this, (see the bug). Rather than rolling your own, I'd recommend using a library to do the platform-specific processing for you.

Apache commons-io has a FileSystemUtils type that provides a static method freeSpaceKb(). It works on Windows and and some Unix implementations (see quote from Javadoc below)

From the Javadoc:

public static long freeSpaceKb(String path) throws IOException

Returns the free space on a drive or volume in kilobytes by invoking the command line. FileSystemUtils.freeSpaceKb("C:"); // Windows FileSystemUtils.freeSpaceKb("/volume"); // *nix

The free space is calculated via the command line. It uses 'dir /-c' on Windows, 'df -kP' on AIX/HP-UX and 'df -k' on other Unix. In order to work, you must be running Windows, or have a implementation of Unix df that supports GNU format when passed -k (or -kP). If you are going to rely on this code, please check that it works on your OS by running some simple tests to compare the command line with the output from this class. If your operating system isn't supported, please raise a JIRA call detailing the exact result from df -k and as much other detail as possible, thanks.

Upvotes: 4

Related Questions