5

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)

Melllvar
  • 2,056
  • 4
  • 24
  • 47
  • 2
    What happens if you get the size of the directory `File` object? I'm assuming you'll get just the FS entry size (maybe 4 KB or so), but who knows... – Vladislav Zorov May 18 '11 at 06:37
  • Size of File for Directories is undefined. Even if it did give me what I want on one device, I can't expect that to be true for all devices. – Melllvar May 18 '11 at 11:31

2 Answers2

2

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.

Nicolas
  • 6,611
  • 3
  • 29
  • 73
  • This worked great, except my `parts[0]` was a `String`, like `1.9G`. So instead of using `Long.parseLong(parts[0])`, I just returned the `String` value. – Joshua Pinter Oct 15 '19 at 02:32
1

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.

Community
  • 1
  • 1
Jason Plank
  • 2,336
  • 5
  • 31
  • 40