B4J Code Snippet Folder size

Author: Erel

Note that it ignores subfolders.

B4X:
Sub SizeOfFilesInFolder(f As String) As Long
   Dim total As Long
   For Each filename As String In File.ListFiles(f)
     If File.IsDirectory(f, filename) = False Then
       total = total + File.Size(f, filename)
     End If
   Next
   Return total
End Sub
 

Magma

Expert
Licensed User
Longtime User
...Well old days created this...

- With this you can read also subfolders... actually using some recursive technique...
- Also you can add other folders to list, or files... like select them for "some" use..

B4X:
private Sub generatelistfolder(genlist As List, ffolder As String) As ResumableSub
 
 
    Dim alist As List
    alist.Initialize
    alist.Clear
 
    Try
        alist=File.ListFiles(ffolder)
    Catch
        Log("Not a Folder, may be a file... will try to add at list if exists...")
    End Try
 
    If alist.Size>0 Then
 

    For k=0 To alist.Size-1
        Dim isfolder As Boolean=File.IsDirectory(ffolder,alist.Get(k))
        
        If isfolder=True Then
            genlist.Add(Array As String(ffolder,alist.Get(k),isfolder))
            If ffolder.EndsWith("\")=True Then
                ffolder=ffolder.SubString2(0,ffolder.Length-1)
            End If
            generatelistfolder(genlist, ffolder & "\" & alist.Get(k))
        Else
            genlist.Add(Array As String(ffolder,alist.Get(k),isfolder))
        End If
    Next
 
    Else
    
        If File.Exists(File.GetFileParent(ffolder),File.GetName(ffolder)) Then
            genlist.add(Array As String(File.GetFileParent(ffolder),File.GetName(ffolder),False))
            Else
            Log ("Not Existing File...")
        End If
    
    End If

Return True

End Sub


You can use it like here:

B4X:
Dim mylist As List  'Here will save the names of Folders, Files and it is folder or file...
Dim totsize As Long=0
mylist.Initialize
mylist.clear

wait for(generatelistfolder(mylist,"D:\tesssst")) complete (s As Boolean) 'add one folder with subfolders
wait for(generatelistfolder(mylist,"c:\ccc")) complete (s As Boolean) 'add a second one... "
wait for(generatelistfolder(mylist,"d:\tameiakh.txt")) complete (s As Boolean) 'add a file at list... "

'Show the Folder | FileName | Is it Folder?
'--------------------------------------------
For k=0 To mylist.Size-1
    Dim FileOrFolderInfo() As String = mylist.Get(k)
    Log(FileOrFolderInfo(0) & " | " & FileOrFolderInfo(1) & " | " & FileOrFolderInfo(2))
    If FileOrFolderInfo(2)=False Then
        totsize=totsize+File.Size( FileOrFolderInfo(0), FileOrFolderInfo(1))
    End If
Next
Log("Total Size in bytes: " & totsize)
Log("Files & Folders Listed: " & mylist.Size)
 

LucaMs

Expert
Licensed User
Longtime User
The reason why I was looking for how to get the size of a folder (I was hoping to find a "direct" command, Java, but I found this, which was enough, I "transcribed" here it and if you think about it for a moment it is also multiplatform. Now, though, I'm about to start looking for a direct command.)

Windows 7 Explorer. When I hover the mouse cursor over a folder, sometimes a popup appears giving me the size of it but not always :oops: :mad:. So I'm afraid I'll have to develop a little (B4J) tool that lists the folder names and their size.
 

LucaMs

Expert
Licensed User
Longtime User
I'm about to start looking for a direct command.
ChatGPT "says" that the following Java function should work:

B4X:
    public static long getSizeOfFolder(String folderPath) throws IOException {
        Path path = Paths.get(folderPath);
        if (!Files.isDirectory(path)) {
            throw new IllegalArgumentException("La directory specificata non esiste o non è una cartella.");
        }

        FileStore fileStore = Files.getFileStore(path);
        return fileStore.getTotalSpace() - fileStore.getUnallocatedSpace();
    }
 

Daestrum

Expert
Licensed User
Longtime User
Your ChatGPT version just returns the used space of my disk irrespective of which folder I choose.

try this
B4X:
import java.io.*;
import java.nio.file.*;
public static long folderSize(String pth) throws IOException {
    Path folder = Paths.get(pth);
    long size = Files.walk(folder)
      .filter(p -> p.toFile().isFile())
      .mapToLong(p -> p.toFile().length())
      .sum();
    return size / 1_048_576;  // (MiB)
}
 
Last edited:

LucaMs

Expert
Licensed User
Longtime User
With the help of ChatGPT (to whom I had to teach many things about B4J 😄 , who knows if it will remember them) I obtained this function (still to be thoroughly tested):
B4X:
Sub GetSizeOfFolder(FolderPath As String) As Long
    Try
        Dim objFiles As JavaObject
        objFiles.InitializeStatic("java.nio.file.Files")
       
        Dim FolderFile As JavaObject
        FolderFile.InitializeNewInstance("java.io.File", Array As Object(FolderPath))
        Dim Path As JavaObject
        Path = FolderFile.RunMethod("toPath", Null)
     
        If Not(File.IsDirectory(FolderPath, "")) Then
            Log("The specified directory does not exist or is not a folder.")
            Return -1
        End If
       
        Dim FileStore As JavaObject
        FileStore = objFiles.RunMethod("getFileStore", Array As Object(Path))
        Dim TotalSpace As Long
        TotalSpace = FileStore.RunMethod("getTotalSpace", Null)
        Dim UnallocatedSpace As Long
        UnallocatedSpace = FileStore.RunMethod("getUnallocatedSpace", Null)
       
        Return TotalSpace - UnallocatedSpace
    Catch
        Log(LastException)
        Return -1
    End Try
End Sub

And after all this effort, maybe this function is slower than the one written by Erel.
 

LucaMs

Expert
Licensed User
Longtime User
Your ChatGPT version just returns the used space of my disk irrespective of which folder I choose.

try this
B4X:
import java.io.*;
import java.nio.file.*;
public static long folderSize(String pth) throws IOException {
    Path folder = Paths.get(pth);
    long size = Files.walk(folder)
      .filter(p -> p.toFile().isFile())
      .mapToLong(p -> p.toFile().length())
      .sum();
    return size / 1_048_576;  // (MiB)
}
Thanks @Daestrum, but... I can not 😄:confused:
I don't know whether to use JavaObject (as I asked ChatGPT to do, see my previous post), Reflection or Inline Java.
 

Daestrum

Expert
Licensed User
Longtime User
Looking at the api, it appears filestore is drive/volume based.
Storage for files. A FileStore represents a storage pool, device, partition, volume, concrete file system or other implementation specific means of file storage. The FileStore for where a file is stored is obtained by invoking the getFileStore method
 

stevel05

Expert
Licensed User
Longtime User
I vaguely remember looking for something similar a while ago. I think my conclusion was that the information is not stored by the OS and is calculated as needed. Probably by iterating the files in the directory. Needless to say I didn't find a better solution, that's not to say there isn't one.
 

Magma

Expert
Licensed User
Longtime User
(general talking)

Correct me if I am wrong.... the filesystem would have to pay the cost of maintaining these counts every time a new file was created or deleted, instead of right now, where the filesystem doesn't have to...

1. So this will be a cost of Indexing... and keep size info too ---> less free space
2. Slower access
3. ...

Even at ubuntu... need to count every time the folders and the files... to give me the size when right click / properties...
 

Magma

Expert
Licensed User
Longtime User
* also, I remember... when searching too about faster proccessing those... was using MFT - but this will need i think some special jar library may be targetting .Net

* also at powershell terminal seems that searching folders is much faster... than IDE... Get-ChildItem -Recurse | Measure-Object).Count
 

LucaMs

Expert
Licensed User
Longtime User
I vaguely remember looking for something similar a while ago. I think my conclusion was that the information is not stored by the OS and is calculated as needed. Probably by iterating the files in the directory. Needless to say I didn't find a better solution, that's not to say there isn't one.
Yes, I think I need to use a B4J recursive Sub, which I assume is the same thing the following Java command does:
Files.walk(folder)


[Also, I was wrong to write this stuff here; I was in too much of a hurry when I created this thread and I didn't look carefully at either the code or the name of the function created by Erel, which is useful but not what I need]
 

Magma

Expert
Licensed User
Longtime User
Yes, I think I need to use a B4J recursive Sub, which I assume is the same thing the following Java command does:



[Also, I was wrong to write this stuff here; I was in too much of a hurry when I created this thread and I didn't look carefully at either the code or the name of the function created by Erel, which is useful but not what I need]
Don't worry... this is a productive thread for all... I think will help others and ourselves to find better and faster solutions...

* It is nice to sharing
 

Daestrum

Expert
Licensed User
Longtime User
That code I posted is the fastest I've found, as it uses nio.
I get times of around 35ms to execute on a 350MB folder.

Odlly enough (I know not to do with this thread ) but if I run B4J as administrator (for access permissions etc) it takes longer.
 

LucaMs

Expert
Licensed User
Longtime User
That code I posted is the fastest I've found, as it uses nio.
I get times of around 35ms to execute on a 350MB folder.

Odlly enough (I know not to do with this thread ) but if I run B4J as administrator (for access permissions etc) it takes longer.
Ok, but you know how to use that Java code, I don't ("Java object"? Recflection? "Inline Java"? I absolutely need to spend some time studying how to pass and receive parameters to Inline Java code! Damn laziness 😄)
 
Top