Melllvar
Melllvar

Reputation: 2086

Fastest way to determine size of directory on SD card on Android

What's the quickest, non-hack-involving way of determining the size of a (flat, non-nested) directory on Android? Getting a list of files with the File object and enumerating through them to compute the size is unbearably slow - surely there's a better way?

(I know that I can use threading to compute the size in the background, but that wouldn't be an ideal solution in this case)

Upvotes: 5

Views: 1575

Answers (2)

Nicolas
Nicolas

Reputation: 7121

You can also use this method, similar to the other one proposed

public static long getDirSize(File dir) {
    try {
        Process du = Runtime.getRuntime().exec("/system/bin/du -sc " + dir.getCanonicalPath(), new String[]{}, Environment.getRootDirectory());
        BufferedReader br = new BufferedReader(new InputStreamReader(du.getInputStream()));
        String[] parts = br.readLine().split("\\s+");
        return Long.parseLong(parts[0]);
    } catch (IOException e) {
        Log.w(TAG, "Could not find size of directory " + dir.getAbsolutePath(), e);
    }
    return -1;
}

It returns size in kilobytes, or -1 if an error was encountered.

Upvotes: 2

Jason Plank
Jason Plank

Reputation: 2336

I don't know if this qualifies as a "non-hack" to you, but if you don't want to reinvent the wheel, you could just use the Linux command du. Here's a clip from its manpage:

NAME
       du - estimate file space usage

SYNOPSIS
       du [OPTION]... [FILE]...

DESCRIPTION
       Summarize disk usage of each FILE, recursively for directories.

In particular the parameters -c and -s should interest you:

$ du -sc /tmp
164    /tmp
164    total
$

The number it outputs is the total number of bytes in the directory. I don't know if you want your size in bytes or human-readable format, but -h is there for you if you need that too.

You'll have to read the output from the command. Capturing command output has already been covered in this question, from which I'm going to borrow heavily to provide the following example:

public String du(String fileName) {
    Class<?> execClass = Class.forName("android.os.Exec");
    Method createSubprocess = execClass.getMethod("createSubprocess", String.class, String.class, String.class, int[].class);
    int[] pid = new int[1];
    FileDescriptor fd = (FileDescriptor)createSubprocess.invoke(null, "/system/bin/du -sc", fileName, null, pid);

    BufferedReader reader = new BufferedReader(new InputStreamReader(new FileInputStream(fd)));
    String output = "";
    try {
        String line;
        while ((line = reader.readLine()) != null) {
            output += line + "\n";
        }
    }
    catch (IOException e) {}
    return output;
}

From there you would need to parse the output for the numerical value representing the total size, which I'm leaving out as it should be fairly trivial. Optionally, you could just throw that in the du() function and make the function return an int instead of a String.

Upvotes: 1

Related Questions