A
A
Alexeytur2022-04-04 05:04:51
NTFS
Alexeytur, 2022-04-04 05:04:51

How to know the exact size of a file on disk?

Good afternoon.

I am writing a program in C# that should recursively calculate the size of folders and files on a disk.
Considered that the size of a file on disk is equal to the length of the file, rounded up to an integer number of clusters. You also need to consider compressed/sparse files. To get information about the file system I use the GetDiskFreeSpaceW function, to get the file size - the GetCompressedFileSizeW function.
But now I noticed that there are small files, up to about 500 bytes, which in the "Properties" menu occupy 0 bytes on the disk.

File properties
624a51655789e224951910.png
I experimented, created a file from an empty one, up to 500 bytes it does not take up disk space, and then it starts to take up a whole cluster, even if you start reducing this file to a size of less than 500 bytes.
I found some explanation here
Question - can I somehow get the "correct" size of such files on the disk programmatically, as the "Properties" menu does?
The function I use to get the size of a file

public static long GetFileSizeOnDisk(string file_path)
        {
            string root_dir = "";
            for (int i = 0; i < file_path.Length; i++)
            {
                root_dir += file_path[i];
                if (file_path[i] == '\\' || (i == file_path.Length - 1))
                    break;
            }
            if (!file_path.StartsWith(@"\\?\"))
                file_path = @"\\?\" + file_path; // чтобы не было ошибки при длинных путях
            //FileInfo info = new FileInfo(file_path);
            uint dummy, sectorsPerCluster, bytesPerSector;
            int result = GetDiskFreeSpaceW(root_dir, out sectorsPerCluster, out bytesPerSector, out dummy, out dummy);
            //int result = GetDiskFreeSpaceW(info.Directory.Root.FullName, out sectorsPerCluster, out bytesPerSector, out dummy, out dummy);
            if (result == 0) throw new Win32Exception();
            uint clusterSize = sectorsPerCluster * bytesPerSector;
            uint hosize;
            uint losize = GetCompressedFileSizeW(file_path, out hosize);
            long size;
            size = (long)hosize << 32 | losize;
            return ((size + clusterSize - 1) / clusterSize) * clusterSize;
        }

        [DllImport("kernel32.dll")]
        static extern uint GetCompressedFileSizeW([In, MarshalAs(UnmanagedType.LPWStr)] string lpFileName,
           [Out, MarshalAs(UnmanagedType.U4)] out uint lpFileSizeHigh);

        [DllImport("kernel32.dll", SetLastError = true, PreserveSig = true)]
        static extern int GetDiskFreeSpaceW([In, MarshalAs(UnmanagedType.LPWStr)] string lpRootPathName,
           out uint lpSectorsPerCluster, out uint lpBytesPerSector, out uint lpNumberOfFreeClusters,
           out uint lpTotalNumberOfClusters);

Answer the question

In order to leave comments, you need to log in

1 answer(s)
K
koss4ok, 2022-04-21
@koss4ok

FileInfo file = new FileInfo(@"C:\test.txt");
Console.WriteLine(file.Length);

Didn't find what you were looking for?

Ask your question

Ask a Question

731 491 924 answers to any question