Как я могу получить размер папки или файла на Java?
Получить размер папки или файла
Ответ 1
java.io.File file = new java.io.File("myfile.txt");
file.length();
Это возвращает длину файла в байтах или 0
, если файл не существует. Нет никакого встроенного способа получить размер папки, вам придется рекурсивно пройти дерево каталогов (используя метод listFiles()
файлового объекта, который представляет каталог), и скопируйте размер каталога для себя:
public static long folderSize(File directory) {
long length = 0;
for (File file : directory.listFiles()) {
if (file.isFile())
length += file.length();
else
length += folderSize(file);
}
return length;
}
ПРЕДУПРЕЖДЕНИЕ. Этот метод недостаточно эффективен для использования в производстве. directory.listFiles()
может возвращать null
и вызывать NullPointerException
. Кроме того, он не рассматривает символические ссылки и, возможно, имеет другие режимы отказа. Используйте этот метод.
Ответ 2
Используя java-7 nio api, вычисление размера папки может быть выполнено намного быстрее.
Вот пример, готовый к запуску, который является надежным и не будет генерировать исключение. Он будет регистрировать каталоги, в которые он не может войти или имел проблемы с перемещением. Символы игнорируются, и одновременная модификация каталога не вызовет больше проблем, чем необходимо.
/**
* Attempts to calculate the size of a file or directory.
*
* <p>
* Since the operation is non-atomic, the returned value may be inaccurate.
* However, this method is quick and does its best.
*/
public static long size(Path path) {
final AtomicLong size = new AtomicLong(0);
try {
Files.walkFileTree(path, new SimpleFileVisitor<Path>() {
@Override
public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) {
size.addAndGet(attrs.size());
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult visitFileFailed(Path file, IOException exc) {
System.out.println("skipped: " + file + " (" + exc + ")");
// Skip folders that can't be traversed
return FileVisitResult.CONTINUE;
}
@Override
public FileVisitResult postVisitDirectory(Path dir, IOException exc) {
if (exc != null)
System.out.println("had trouble traversing: " + dir + " (" + exc + ")");
// Ignore errors traversing a folder
return FileVisitResult.CONTINUE;
}
});
} catch (IOException e) {
throw new AssertionError("walkFileTree will not throw IOException if the FileVisitor does not");
}
return size.get();
}
Ответ 3
Вам нужно FileUtils#sizeOfDirectory(File)
из commons-io.
Обратите внимание, что вам нужно будет вручную проверить, является ли файл каталогом, поскольку метод генерирует исключение, если ему передается некаталог.
ПРЕДУПРЕЖДЕНИЕ. Этот метод (с точки зрения commons-io 2.4) имеет ошибку и может бросать IllegalArgumentException
, если каталог изменяется одновременно.
Ответ 4
В Java 8:
long size = Files.walk(path).mapToLong( p -> p.toFile().length() ).sum();
Было бы лучше использовать Files::size
на шаге карты, но он выдает исключенное исключение.
UPDATE:
Вы также должны знать, что это может вызвать исключение, если некоторые из файлов/папок недоступны. Смотрите question и другое решение, используя Guava.
Ответ 5
public static long getFolderSize(File dir) {
long size = 0;
for (File file : dir.listFiles()) {
if (file.isFile()) {
System.out.println(file.getName() + " " + file.length());
size += file.length();
}
else
size += getFolderSize(file);
}
return size;
}
Ответ 6
Для Java 8 это правильный способ:
Files.walk(new File("D:/temp").toPath())
.map(f -> f.toFile())
.filter(f -> f.isFile())
.mapToLong(f -> f.length()).sum()
Важно отфильтровать все каталоги, поскольку метод длины не гарантированно равен 0 для каталогов.
По крайней мере, этот код обеспечивает такую же информацию о размере, что и сам проводник Windows.
Ответ 7
Если вы хотите использовать API Java 8 NIO, следующая программа будет печатать размер в байтах каталога, в котором он находится.
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
public class PathSize {
public static void main(String[] args) {
Path path = Paths.get(".");
long size = calculateSize(path);
System.out.println(size);
}
/**
* Returns the size, in bytes, of the specified <tt>path</tt>. If the given
* path is a regular file, trivially its size is returned. Else the path is
* a directory and its contents are recursively explored, returning the
* total sum of all files within the directory.
* <p>
* If an I/O exception occurs, it is suppressed within this method and
* <tt>0</tt> is returned as the size of the specified <tt>path</tt>.
*
* @param path path whose size is to be returned
* @return size of the specified path
*/
public static long calculateSize(Path path) {
try {
if (Files.isRegularFile(path)) {
return Files.size(path);
}
return Files.list(path).mapToLong(PathSize::calculateSize).sum();
} catch (IOException e) {
return 0L;
}
}
}
Метод calculateSize
универсален для объектов Path
, поэтому он также работает для файлов.
Примечание, что если файл или каталог недоступны, в этом случае возвращаемый размер объекта пути будет 0
.
Ответ 8
File.length()
(Javadoc).
Обратите внимание, что это не работает для каталогов или не гарантируется работа.
Для каталога, что вам нужно? Если это общий размер всех файлов под ним, вы можете рекурсивно ходить с детьми, используя File.list()
и File.isDirectory()
, и суммировать их размеры.
Ответ 9
Объект File
имеет метод length
:
f = new File("your/file/name");
f.length();
Ответ 10
Здесь лучший способ получить общий размер файла (работает для каталога и некаталога):
public static long getSize(File file) {
long size;
if (file.isDirectory()) {
size = 0;
for (File child : file.listFiles()) {
size += getSize(child);
}
} else {
size = file.length();
}
return size;
}
Изменить: обратите внимание, что это, вероятно, займет много времени. Не запускайте его в потоке пользовательского интерфейса.
Кроме того, здесь (взято из fooobar.com/questions/17018/...) это хороший способ получить удобочитаемую строку String из long return:
public static String getReadableSize(long size) {
if(size <= 0) return "0";
final String[] units = new String[] { "B", "KB", "MB", "GB", "TB" };
int digitGroups = (int) (Math.log10(size)/Math.log10(1024));
return new DecimalFormat("#,##0.#").format(size/Math.pow(1024, digitGroups))
+ " " + units[digitGroups];
}
Ответ 11
- Работает для Android и Java
- Работает как для папок, так и для файлов
- Проверяет нулевой указатель везде, где это необходимо
- Игнорирует символическую ссылку aka shortcuts
- Продукция готова!
Исходный код:
public long fileSize(File root) {
if(root == null){
return 0;
}
if(root.isFile()){
return root.length();
}
try {
if(isSymlink(root)){
return 0;
}
} catch (IOException e) {
e.printStackTrace();
return 0;
}
long length = 0;
File[] files = root.listFiles();
if(files == null){
return 0;
}
for (File file : files) {
length += fileSize(file);
}
return length;
}
private static boolean isSymlink(File file) throws IOException {
File canon;
if (file.getParent() == null) {
canon = file;
} else {
File canonDir = file.getParentFile().getCanonicalFile();
canon = new File(canonDir, file.getName());
}
return !canon.getCanonicalFile().equals(canon.getAbsoluteFile());
}
Ответ 12
public long folderSize (String directory)
{
File curDir = new File(directory);
long length = 0;
for(File f : curDir.listFiles())
{
if(f.isDirectory())
{
for ( File child : f.listFiles())
{
length = length + child.length();
}
System.out.println("Directory: " + f.getName() + " " + length + "kb");
}
else
{
length = f.length();
System.out.println("File: " + f.getName() + " " + length + "kb");
}
length = 0;
}
return length;
}
Ответ 13
После много исследований и изучения различных решений, предлагаемых здесь в StackOverflow. Наконец я решил написать собственное решение. Моя цель - иметь механизм без броска, потому что я не хочу сбой, если API не может получить размер папки. Этот метод не подходит для многопоточного сценария.
Прежде всего, я хочу проверить допустимые каталоги при обходе дерева файловой системы.
private static boolean isValidDir(File dir){
if (dir != null && dir.exists() && dir.isDirectory()){
return true;
}else{
return false;
}
}
Во-вторых, я не хочу, чтобы мой рекурсивный вызов включался в символические ссылки (программные ссылки) и включал размер в общую совокупность.
public static boolean isSymlink(File file) throws IOException {
File canon;
if (file.getParent() == null) {
canon = file;
} else {
canon = new File(file.getParentFile().getCanonicalFile(),
file.getName());
}
return !canon.getCanonicalFile().equals(canon.getAbsoluteFile());
}
Наконец, моя реализация на основе рекурсии позволяет получить размер указанной директории. Обратите внимание на нулевую проверку для dir.listFiles(). Согласно javadoc существует вероятность того, что этот метод может вернуть null.
public static long getDirSize(File dir){
if (!isValidDir(dir))
return 0L;
File[] files = dir.listFiles();
//Guard for null pointer exception on files
if (files == null){
return 0L;
}else{
long size = 0L;
for(File file : files){
if (file.isFile()){
size += file.length();
}else{
try{
if (!isSymlink(file)) size += getDirSize(file);
}catch (IOException ioe){
//digest exception
}
}
}
return size;
}
}
Некоторые кремы на торте, API, чтобы получить размер списка Файлы (возможно, все файлы и папки под root).
public static long getDirSize(List<File> files){
long size = 0L;
for(File file : files){
if (file.isDirectory()){
size += getDirSize(file);
} else {
size += file.length();
}
}
return size;
}
Ответ 14
в linux, если вы хотите отсортировать каталоги, тогда du -hs * | sort -h
Ответ 15
для окон, использующих java.io, эта рекурсивная функция полезна.
public static long folderSize(File directory) {
long length = 0;
if (directory.isFile())
length += directory.length();
else{
for (File file : directory.listFiles()) {
if (file.isFile())
length += file.length();
else
length += folderSize(file);
}
}
return length;
}
Это проверено и работает правильно с моей стороны.