使用 java 获取目录大小

Get directory size using java

提问人:Svetlana 提问时间:11/4/2023 更新时间:11/4/2023 访问量:81

问:

我的代码有几个测试要通过。程序的目的是找到某个目录的大小。测试包括目录不存在、目录存在但为空以及目录不为空的情况。

计算目录大小的方法:

其中只是一个字符串,而不是绝对或相对路径。
public long checkSize(String directoryName)directoryName

因此,测试资源具有如下结构(使用 Idea IDE 查看):

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

目录“cats”实际上位于以下路径:
/C:/dev/DirectorySize/target/test-classes/cats

并且方法仅获取字符串“cats”(我的意思是这里==“cats”)。checkSize(String directoryName)directoryName

我的意思是通过键入以下内容来获取目录的 URL:
URL resource = getClass().getClassLoader().getResource(directoryName)

上面的代码适用于不存在的目录,因为它返回 null(例如 == “龙”)。但是,对于存在但为空的目录,它也会返回 null(例如 == “老鼠”)。directoryNamedirectoryName

这就是我的问题。如何获得具有这种结构的现有但非空目录的大小?

java file-io 目录

评论

0赞 andersen 11/4/2023
你能分享代码吗?
1赞 Jorn 11/4/2023
这有关系吗?您可以只为两者返回 0。只要你用的是资源系统,你就真的做不到这一点。资源并不总是在文件系统上,因此您不能假定它们位于常规文件夹树中。如果需要文件夹树属性,请直接使用路径,而不是资源。
0赞 Svetlana 11/4/2023
@andersen pastebin.com/Nc5wM6YU
0赞 Svetlana 11/4/2023
@Jorn 对不起,我需要为不存在的目录抛出异常。如果您知道如何找到某个目录的路径,只有它的名字,请写下它。我真的很高兴知道它。
0赞 VGR 11/5/2023
如果您的代码在 Java 模块中运行,则可以使用 ModuleReader.list() 查找资源“目录”下的所有内容。如果您不在模块中运行,则没有安全的方法可以执行此操作。你可能认为你已经找到了一个黑客,但这个黑客最终会失败

答:

0赞 Stephen C 11/4/2023 #1

没有内置支持查找目录的大小。事实上,这并不是一个定义明确的概念:有很多方法可以测量“大小”。

但是 Java SE 确实提供了接口 (javadoc),允许您遍历文件系统中的目录树,访问每个目录和文件;请参阅 Java 教程:遍历文件树,了解有关如何使用它的详尽说明。要计算目录的大小(无论这意味着什么),您需要遍历树并计算文件的数量,或者将它们的文件大小相加,或者其他什么。FileVisitor


我的意思是通过键入以下内容来获取目录的 URL:

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

还行。。。所以现在这变得混乱/困惑。只有当目录位于应用程序类路径上时,才能以这种方式访问该目录。这将包括“目录”实际上是在JAR或ZIP文件中,或者......基本上任何事情,如果你考虑到自定义类加载器。没有标准方法可以从 返回的 URL 中获取事物的大小。因此,如果你真的在谈论文件系统中的事情,那么使用是错误的起点。但是,如果你真的指的是“类路径上的目录”,那么你的问题就真的很难了。getResource()getResource()

2赞 Keyboard Corporation 11/4/2023 #2

对于 Java 8 及更高版本,可以使用 和 .java.nio.file.Filesjava.nio.file.Path

该方法可用于递归遍历目录,并且该方法可用于获取每个文件的大小。Files.walk()Files.size()

然后,可以通过将所有文件的大小相加来计算目录的总大小。

例:

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;
}

此方法首先创建一个对象,表示目录及其子目录中的所有文件。然后,它会过滤掉任何不是常规文件的路径(即,目录和符号链接被忽略),并将每个文件路径映射到其大小(以字节为单位)。如果在尝试获取文件大小时发生 an,该方法将打印一条错误消息,并返回该文件的大小 0。最后,它将所有文件的大小相加,以获得目录的总大小。StreamPathIOException

可以使用字符串形式的目录名称调用此方法。例如,如果目录位于 ,则可以调用 checkSize(“cats”)。/C:/dev/DirectorySize/target/test-classes/cats

*请注意,如果目录不存在为空,则此方法将。如果要区分这两种情况,可以修改方法,在目录不存在时抛出异常或返回特殊值。return 0


处理现有或空

  1. 您需要检查该目录是否存在。可以使用该方法,该方法将返回文件或目录是否存在,否则将返回该方法。Files.exists()truefalse
Path path = Paths.get("path_to_directory");
boolean exists = Files.exists(path);
  1. 如果该目录存在,则可以检查它是否为空。可以使用该方法,该方法返回表示目录中条目的对象。如果目录为空,则流将为空。Files.list()StreamPath
if (exists) {
   boolean isEmpty = !Files.list(path).findAny().isPresent();
}
  1. 要处理这些情况,您可以使用(如果这是 Java 8 +)。可用于表示可为 null 的对象引用,它可以帮助您区分不存在的目录和空目录。Optional classOptional class
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();
   }
}

评论

0赞 Svetlana 11/4/2023
您能否注意如何修改方法以区分不存在和空目录的情况?我只是尝试了几种方法,但似乎没有什么能真正帮助我解决这个问题。
0赞 Keyboard Corporation 11/4/2023
我把它加在我的答案上。
0赞 Svetlana 11/4/2023
我不知道这是怎么回事。似乎它对我不起作用。例如,我想到达空的“rats”文件夹。而不是像我得到的那样有一个路径,当然代码假设目录“rats”不存在。/C:/dev/DirectorySize/target/test-classes/ratsC:\dev\DirectorySize\rats