在Java开发中,获取文件大小是一项常见且基础的操作,无论是文件上传下载、进度展示还是存储空间管理,都离不开对文件大小的准确获取,本文将系统介绍Java中获取文件大小的多种方法,涵盖不同场景下的实现细节及注意事项,帮助开发者选择最合适的方案。

使用File类的length()方法获取文件大小
Java.io.File类提供了最直接的文件大小获取方式——length()方法,该方法返回文件内容的字节数,对于常规文件(如.txt、.jpg等),返回值即为文件的实际大小;对于目录(文件夹),则返回值不确定,具体取决于操作系统的实现,因此不建议对目录使用该方法。
核心代码示例:
import java.io.File;
public class GetFileSize {
public static void main(String[] args) {
File file = new File("example.txt");
if (file.exists() && file.isFile()) {
long fileSize = file.length();
System.out.println("文件大小: " + fileSize + " 字节");
} else {
System.out.println("文件不存在或不是普通文件");
}
}
}
注意事项:
- 文件存在性检查:调用length()前需通过
exists()确认文件是否存在,避免因文件不存在抛出异常。 - 单位转换:length()返回的是字节数,通常需要转换为KB、MB等更易读的单位,可通过
fileSize / 1024等方式实现。 - 性能考虑:length()方法仅读取文件元数据,不涉及文件内容读取,因此性能较高,适合频繁调用。
使用Files类的size()方法(Java 7+)
Java 7引入的NIO.2(New I/O)提供了更强大的文件操作能力,其中java.nio.file.Files类的size()方法可以替代File类的length()方法,且在功能上更加完善。
核心代码示例:
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class GetFileSizeWithNIO {
public static void main(String[] args) {
Path path = Paths.get("example.txt");
if (Files.exists(path) && !Files.isDirectory(path)) {
try {
long fileSize = Files.size(path);
System.out.println("文件大小: " + fileSize + " 字节");
} catch (Exception e) {
System.out.println("获取文件大小失败: " + e.getMessage());
}
} else {
System.out.println("文件不存在或为目录");
}
}
}
优势对比:

- 异常处理:Files.size()会抛出IOException,需显式处理,而File.length()不抛出受检异常,更简洁。
- 路径灵活性:NIO的Path接口支持更复杂的路径操作,如符号链接处理、相对路径解析等。
- 功能扩展性:Files类提供了丰富的文件操作方法(如读取属性、复制文件等),与size()方法配合使用更高效。
通过文件输入流获取文件大小
在某些特殊场景下(如文件正在被写入或需要校验文件完整性),可以通过打开文件输入流并读取剩余字节数来获取文件大小,这种方法虽然不如前两种高效,但在需要同时读取文件内容时可以减少IO操作。
核心代码示例:
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
public class GetFileSizeWithStream {
public static void main(String[] args) {
try (InputStream inputStream = new FileInputStream("example.txt")) {
long fileSize = 0;
while (inputStream.read() != -1) {
fileSize++;
}
System.out.println("文件大小: " + fileSize + " 字节");
} catch (IOException e) {
System.out.println("获取文件大小失败: " + e.getMessage());
}
}
}
适用场景:
- 动态文件:对于正在被写入的文件,通过流读取可以获取到当前已写入的字节数。
- 数据校验:在读取文件内容的同时计算文件大小,可用于校验文件是否完整。
缺点:
- 性能开销大:需要逐字节读取文件,耗时较长,不适用于大文件。
- 资源占用:需手动关闭流或使用try-with-resources语句,避免资源泄漏。
获取目录总大小
若需要计算目录及其所有子目录中文件的总大小,需采用递归遍历的方式,File类的listFiles()方法结合递归可以实现这一功能,而NIO.2则提供了更优雅的解决方案。
递归实现示例(File类):

import java.io.File;
public class GetDirectorySize {
public static long getDirectorySize(File dir) {
long size = 0;
if (dir.isDirectory()) {
File[] files = dir.listFiles();
if (files != null) {
for (File file : files) {
if (file.isFile()) {
size += file.length();
} else {
size += getDirectorySize(file);
}
}
}
}
return size;
}
public static void main(String[] args) {
File dir = new File("exampleDir");
if (dir.exists() && dir.isDirectory()) {
long totalSize = getDirectorySize(dir);
System.out.println("目录总大小: " + totalSize + " 字节");
}
}
}
NIO.2实现示例(Files类):
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 class GetDirectorySizeWithNIO {
public static long getDirectorySize(Path path) throws IOException {
try (Stream<Path> walk = Files.walk(path)) {
return walk.filter(Files::isRegularFile)
.mapToLong(p -> {
try {
return Files.size(p);
} catch (IOException e) {
return 0;
}
})
.sum();
}
}
public static void main(String[] args) {
Path dir = Paths.get("exampleDir");
if (Files.exists(dir) && Files.isDirectory(dir)) {
try {
long totalSize = getDirectorySize(dir);
System.out.println("目录总大小: " + totalSize + " 字节");
} catch (IOException e) {
System.out.println("获取目录大小失败: " + e.getMessage());
}
}
}
}
NIO.2的优势:
- 流式处理:使用Stream API并行处理文件,提高大目录的遍历效率。
- 异常处理:通过filter和mapToLong中的异常捕获,确保单个文件错误不影响整体计算。
注意事项与最佳实践
- 单位标准化:建议将文件大小转换为易读的单位(如KB、MB),可通过以下方法实现:
public static String formatFileSize(long size) { if (size < 1024) return size + " B"; int exp = (int) (Math.log(size) / Math.log(1024)); char pre = "KMGTPE".charAt(exp - 1); return String.format("%.1f %sB", size / Math.pow(1024, exp), pre); } - 符号链接处理:使用NIO.2时,可通过
Files.readAttributes(path, BasicFileAttributes.class).isSymbolicLink()判断符号链接,避免重复计算。 - 并发安全:在多线程环境下,若文件可能被其他进程修改,需考虑加锁或使用实时监控机制(如WatchService)。
- 性能优化:对于频繁访问的文件大小信息,可考虑缓存结果,但需注意及时更新以避免数据不一致。
获取Java文件大小的方法多种多样,开发者应根据实际场景选择合适的方案:对于简单文件大小获取,优先使用File.length()或Files.size();对于目录大小计算,推荐NIO.2的流式处理;特殊场景下可通过文件流读取动态获取,无论选择哪种方法,都需注意异常处理、单位转换和性能优化,以确保代码的健壮性和可维护性。




















