Задать вопрос
Alexeytur
@Alexeytur

Как точно узнать размер файла на диске?

Добрый день.

Пишу на C# программу, которая должна высчитывать рекурсивно размер папок и файлов на диске.
Считал, что размер файла на диске равен длине файла, округленной вверх до целого числа кластеров. Также нужно нужно учитывать сжатые/разреженные файлы. Для получения данных о файловой системе использую функцию GetDiskFreeSpaceW, для получения размера файла - функцию GetCompressedFileSizeW.
Но сейчас заметил, что есть маленькие файлы, примерно до 500 байт, которые в меню "Свойства" занимают 0 байт на диске.
Свойства файла
624a51655789e224951910.png
Экспериментировал, создавал файл с пустого, до 500 байт он не занимает места на диске, а потом начинает занимать целый кластер, даже если начать уменьшать этот файл до размера меньше 500 байт.
Здесь нашел какое-то объяснение
Вопрос - можно как-нибудь получить программно "правильный" размер таких файлов на диске, как это делает меню "Свойства"?
Функция, которую использую для получения размера файла

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

  • Вопрос задан
  • 888 просмотров
Подписаться 3 Простой 6 комментариев
Пригласить эксперта
Ответы на вопрос 1
@koss4ok
FileInfo file = new FileInfo(@"C:\test.txt");
Console.WriteLine(file.Length);
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы