Getting the capacity of a disk

What I want to do is programatically get either:
(a) the capacity of a disk, such as a hard drive or
(b) the remaining space - preferably in bytes, but I’m flexible.

I’ll settle for just one of these, or a pointer to the API that allows this.

Any ideas?

You can’t do this with Java yet. I found the RFE for it though:

http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4057701

It says it’s targeted for 1.6. So until then, there’s not much you can do unless you use a native call.

Many of us have been waiting since 1.1 for this, so don’t hold your breath - expect it to be delayed until java 10 or something.

I mean, knowing whether you can move a file without corrupting it, and whether you can make a new file, and stuff like that, aren’t important are they? No-one ever writes a server that is intelligent enough not to crash the OS by taking up too much space with it’s logfiles, do they? Nor puts any defensive code in their clients?
</bitter, bitter sarcasm>

this only works on windows. its a hack and yes i agree
with bla on this one also. bit of an on going joke.


public static final long getFreeSpace(File file) throws IllegalArgumentException, IllegalStateException, IOException {
            if (file == null) throw new IllegalArgumentException("file == null");
 
            if (System.getProperty("os.name").startsWith("Windows")) 
                  return getFreeSpaceInWindows(file);
            //else if (System.getProperty("os.name").startsWith("..."))
            //      return ...
            else
                  throw new IllegalStateException("getFreeSpace(File) currently does not support this operating system: " + System.getProperty("os.name"));
      }
 
 
      private static final long getFreeSpaceInWindows(File file) throws IllegalStateException, IOException {
            PrintWriter writer = null;
            BufferedReader reader = null;
            try {
                        // create a temp .bat file to run the dir command:
                  File script = File.createTempFile("script", ".bat");
                  script.deleteOnExit();
                  writer = new PrintWriter( new FileWriter(script, false), true );
                  writer.println("dir \"" + file.getCanonicalPath() + "\"");
                  writer.close();      // MUST close it at this point, else the Process below will fail to run
                  
                        // get output from running the .bat file:
                  Process p = Runtime.getRuntime().exec( script.getAbsolutePath() );
                  reader = new BufferedReader( new InputStreamReader( p.getInputStream() ) );
                  String line = null;
                  while (true) {
                        line = reader.readLine();
                        if (line == null) throw new IllegalStateException("Failed to encounter the expected output (a line ending with the text \"free\") while parsing the output of the dir command");
                        else if (line.endsWith("free")) break;
                  }
                  // Here are some real examples seen of what line can look like:
                  //        12 dir(s)     631,889,920 bytes free
                  //        10 dir(s)     24,167.73 MB free
                  //                      788,021,248 bytes free
                  // (This last case happens if there are no contents inside volume)
                  // The parsing code below MUST handle all these cases
 
                        // parse the number (of bytes free) from line:
                  String[] tokens = line.split("\\s+", -1);      // in ALL cases, should have tokens[tokens.length - 3] = "788,021,248", tokens[tokens.length - 2] = "bytes" or "KB" or "MB" or "GB", tokens[tokens.length - 1] = "free"
                  String numberText = tokens[tokens.length - 3].replaceAll(",", "");      // replaceAll eliminates the commas but NOT any decimal point
                  String unit = tokens[tokens.length - 2];
                  if (unit.equals("bytes"))
                        return Long.parseLong(numberText);
                  else {
 
                        System.err.println("--------------------------------------------------");
                        System.err.println("WARNING: POSSIBLE LOSS OF PRECISION in determining the free space");
                        System.err.println("The operating system reported the free space as " + numberText + " " + unit);
                        System.err.println("This output may have been rounded, however, which means that the exact number of bytes is impossible to determine");
                        System.err.println("--------------------------------------------------");
                        double number = Double.parseDouble(numberText);
                        if (unit.equals("KB")) return (long) (number * 1024);      // see       http://groups.google.com/groups?dq=&hl=en&lr=&ie=UTF-8&threadm=QNJ6c.54315%24H44.994342%40bgtnsc04-news.ops.worldnet.att.net&prev=/groups%3Fhl%3Den%26lr%3D%26ie%3DUTF-8%26group%3Dcomp.os.msdos.programmer
                        else if (unit.equals("MB")) return (long) (number * 1024 * 1024);
                        else if (unit.equals("GB")) return (long) (number * 1024 * 1024 * 1024);
                        else throw new IllegalStateException("Program encountered unit = " + unit + " which it is unable to handle");
                  }
            }
            finally {
                  if (writer != null) writer.close();
                  if (reader != null) reader.close();
            }
      }

oh to note- u could do a .sh script on macosx i guess.
but then under mac i think theres a java call that can
give u this info if u use there os java additions.

[quote]this only works on windows. its a hack and yes i agree
with bla on this one also. bit of an on going joke.
[/quote]
This code works fine on Linux. On Windows the exec(“dir”) will fail. Since the latest Mac OS is UNIX-based, a similar code should work well on it. So we can conclude that Windows sucks. ;D


            Process p;
            if (System.getProperty("os.name").startsWith("Windows")) {
                  p = Runtime.getRuntime().exec("dir");
            } else if (System.getProperty("os.name").startsWith("Linux")) {
                  p = Runtime.getRuntime().exec("df");
            } else {
                  return;
            }
            
            BufferedReader r = new BufferedReader(new InputStreamReader(p.getInputStream()));
            
            String line;
            while ((line = r.readLine()) != null) {
                  System.out.println(line);
            }

You need to do:

p = Runtime.getRuntime().exec(“cmd.exe /c dir”);

for windows

Well, that’s too bad. I was hoping for a platform independent solution. I’m writing a quick app that will helps you manage your disk space.

The idea is to solve this problem: Say you want to add more music to your digital music library, and you need about 1.5 GB - but you’ve only got 700 MB left on your hard disk. Or maybe you want to install that new game and need to get rid of something before it will fit. So, it’s time to clean out the old hard disk, but what to delete/uninstall? Well this program would visually allow you to see how your space is being used, and what files/directories are taking up more than their fair share of space, allowing to you make a quick, informed decision.

I can live without the “get disk capacity” Java feature, but it sure would be nice. It’s gotta run on at least Win and Mac - without any hack code. But I do appreciate the answers.

Have you checked out jDiskReport?

Platform independant and pretty accurate.


   public static final long getFreeDiskSpaceAtRoot(File root)
   {
      try
      {
         // CREATE FILE AS BIG AS POSSIBLE

         final File file = new File(root.getAbsolutePath() + "big_temp_file_should_have_been_deleted.txt");

         final RandomAccessFile raf = new RandomAccessFile(file, "rw");

         long size = 0;
         long step = Long.MAX_VALUE / 2;

         while (step > 0)
         {
            try
            {
               raf.setLength(size + step);

               size += step;
            }
            catch (java.io.IOException ioe)
            {
               step /= 2;
            }
         }

         raf.close();

         // DELETE FILE

         file.delete();

         return size;
      }
      catch (Exception exc)
      {
         exc.printStackTrace();

         return -1;
      }
   }

No need to wait for 1.6 ;D