Home > front end >  Get directory size using java
Get directory size using java

Time:11-05

I have several test to pass with my code. The aim of a program is to find size of certain directory. Tests include cases with an non-existent directory, existent but empty directory and non-empty existent directory.

A method counting the directory size:
public long checkSize(String directoryName).
Where directoryName is only a String and not an absolute or relative path.

So the test resources have a structure like this (viewed with Idea IDE):

    /test
        /resources
            /cats
                /cat.jpg
            /rats (empty)

And directory 'cats' is actually located at this path:
/C:/dev/DirectorySize/target/test-classes/cats

And method checkSize(String directoryName) gets a String "cats" only (I mean here directoryName == "cats").

I meant to get an URL of a directory by typing this:
URL resource = getClass().getClassLoader().getResource(directoryName)

The code above works well with non-existent directory as it returns null (e.g. directoryName == "dragons"). However it also returns null for existent but empty directory (e.g. directoryName == "rats").

So that is my problem. How can I get a size of an existent but non-empty directory with such a structure?

CodePudding user response:

There is no built-in support for finding the size of a directory. Indeed, it is not really a well-defined concept: there are many ways to measure the "size".

But Java SE does provide the FileVisitor interface (javadoc) that allows you to traverse a directory tree in the file system, visiting each of the directories and files; see Java Tutorial: Walking the file tree for a thorough explanation on how to use it. To compute the size of a directory (what ever that means), you would traverse the tree and count the number of files, or add up their file sizes, or whatever.


I meant to get an URL of a directory by typing this:

 URL resource = getClass().getClassLoader().getResource(directoryName)

OK ... so now this gets confused / confusing. You can only access a directory that way if it is on the applications classpath. And this will include "directories" are actually in JAR or ZIP files or ... basically anything, if you take account of custom classloaders. There is no standard way to get the size of things from a URL returned by getResource(). So if you are really talking about things in the file system, using getResource() is the wrong place to start. But if you genuinely mean "a directory on the classpath", your problem is really hard.

CodePudding user response:

For Java 8 and above, you can use the java.nio.file.Files and java.nio.file.Path.

The Files.walk() method can be used to walk a directory recursively, and the Files.size() method can be used to get the size of each file.

The total size of the directory can then be calculated by summing the sizes of all the files.

Example:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.stream.Stream;

public long checkSize(String directoryName) {
   long size = 0;
   try (Stream<Path> walk = Files.walk(Paths.get(directoryName))) {
       size = walk
               .filter(Files::isRegularFile)
               .mapToLong(p -> {
                  try {
                      return Files.size(p);
                  } catch (IOException e) {
                      System.out.printf("Failed to get size of %s%n%s", p, e);
                      return 0L;
                  }
               })
               .sum();
   } catch (IOException e) {
       System.out.printf("IO errors %s", e);
   }
   return size;
}

This method first creates a Stream of Path objects representing all files in the directory and its subdirectories. It then filters out any paths that are not regular files (i.e., directories and symbolic links are ignored), and maps each file path to its size in bytes. If an IOException occurs when trying to get the size of a file, the method prints an error message and returns a size of 0 for that file. Finally, it sums up the sizes of all the files to get the total size of the directory.

You can call this method with the name of the directory as a string. For example, if the directory is located at /C:/dev/DirectorySize/target/test-classes/cats, you can call checkSize("cats").

*Please be note that this method will return 0 if the directory does not exist or is empty. If you want to distinguish between these two cases, you can modify the method to throw an exception or return a special value when the directory does not exist.


Handling existing or empty

  1. You need to check if the directory exists. You can use the Files.exists() method, which returns true if the file or directory exists and false otherwise.
Path path = Paths.get("path_to_directory");
boolean exists = Files.exists(path);
  1. If the directory exists, you can then check if it is empty. You can use the Files.list() method, which returns a Stream of Path objects representing the entries in the directory. If the directory is empty, the stream will be empty.
if (exists) {
   boolean isEmpty = !Files.list(path).findAny().isPresent();
}
  1. To handle these cases, you can use the Optional class(if this is Java 8 ). The Optional class can be used to represent nullable object references, and it can help you distinguish between a non-existent directory and an empty directory.
public Optional<Path> getDirectory(String pathString) {
   Path path = Paths.get(pathString);
   if (Files.exists(path)) {
       if (Files.list(path).findAny().isPresent()) {
           return Optional.of(path);
       } else {
           return Optional.empty();
       }
   } else {
       return Optional.empty();
   }
}
  • Related