Подтвердить что ты не робот

Получить размер файла без использования System.IO.FileInfo?

Можно ли получить размер файла на С# без использования System.IO.FileInfo?

Я знаю, что вы можете получить другие вещи, такие как Name и Extension, используя Path.GetFileName(yourFilePath) и Path.GetExtension(yourFilePath) соответственно, но, видимо, не размер файла? Есть ли другой способ получить размер файла без использования System.IO.FileInfo?

Единственная причина этого в том, что, если я прав, FileInfo захватывает больше информации, чем мне действительно нужно, поэтому для сбора всех этих файлов требуется больше времени, если мне нужно только размер файла. Есть ли более быстрый способ?

4b9b3361

Ответ 1

Я выполнил тест, используя эти два метода:

    public static uint GetFileSizeA(string filename)
    {
        WIN32_FIND_DATA findData;
        FindFirstFile(filename, out findData);
        return findData.nFileSizeLow;
    }

    public static uint GetFileSizeB(string filename)
    {
        IntPtr handle = CreateFile(
            filename,
            FileAccess.Read,
            FileShare.Read,
            IntPtr.Zero,
            FileMode.Open,
            FileAttributes.ReadOnly,
            IntPtr.Zero);
        long fileSize;
        GetFileSizeEx(handle, out fileSize);
        CloseHandle(handle);
        return (uint) fileSize;
    }

Запустив бит поверх 2300 файлов, GetFileSizeA выполнил 62-63 мс для запуска. GetFileSizeB занял более 18 секунд.

Если кто-то не видит что-то, что я делаю неправильно, я думаю, что ответ ясно, какой метод быстрее.

Есть ли способ воздержаться от фактического открытия файла?

Обновление

Изменение параметров FileAttributes.ReadOnly в FileAttributes.Normal сокращает время так, чтобы эти два метода были идентичны по производительности.

Кроме того, если вы пропустите вызов CloseHandle(), метод GetFileSizeEx станет примерно на 20-30% быстрее, хотя я не знаю, что рекомендую это.

Ответ 2

Из короткого теста, который я сделал, я обнаружил, что использование FileStream в среднем на 1 миллисекунду меньше, чем использование Pete GetFileSizeB (заняло около 21 миллисекунды по сетевому ресурсу...). Лично я предпочитаю оставаться в пределах BCL, когда я могу.

Код прост:

using (var file = new FileStream(path, FileMode.Open, FileAccess.Read, FileShare.ReadWrite))
{
    return file.Length;
}

Ответ 3

Как этот комментарий:

У меня есть небольшое приложение, которое собирает информацию о размере и сохраняет его в массив... но у меня часто есть полмиллиона файлов, давайте или принимаем, и для этого требуется время, чтобы пройти через все эти файлы (я используя FileInfo). Мне просто интересно, был ли более быстрый способ...

Поскольку вы находите длину столь большого количества файлов, вы, скорее всего, выиграете от распараллеливания, чем от попыток получить размер файла с помощью другого метода. Класс FileInfo должен быть достаточно хорош, и любые улучшения, вероятно, будут небольшими.

С другой стороны, параллелизация запросов размера файла может значительно улучшить скорость. (Обратите внимание, что степень улучшения будет в значительной степени основана на вашем дисководе, а не на вашем процессоре, поэтому результаты могут сильно различаться.)

Ответ 4

Не прямой ответ... потому что я не уверен, что существует более быстрый способ использования платформы .NET.

Вот код, который я использую:

  List<long> list = new List<long>();
  DirectoryInfo di = new DirectoryInfo("C:\\Program Files");
  FileInfo[] fiArray = di.GetFiles("*", SearchOption.AllDirectories);
  foreach (FileInfo f in fiArray)
    list.Add(f.Length);

Запустив это, потребовалось 2709 мс для запуска в моем каталоге "Program Files", который составлял около 22720 файлов. Это не сутулость. Кроме того, когда я положил *.txt в качестве фильтра для первого параметра метода GetFiles, он резко сократил время до 461 мс.

Многое будет зависеть от того, насколько быстро ваш жесткий диск, но я действительно не думаю, что FileInfo убивает производительность.

ПРИМЕЧАНИЕ. Я использую это только для .NET 4 +

Ответ 5

Вы можете попробовать следующее:

[DllImport("kernel32.dll")]
static extern bool GetFileSizeEx(IntPtr hFile, out long lpFileSize);

Но это не очень хорошее улучшение...

Вот пример кода, взятого из pinvoke.net:

IntPtr handle = CreateFile(
    PathString, 
    GENERIC_READ, 
    FILE_SHARE_READ, 
    0, 
    OPEN_EXISTING, 
    FILE_ATTRIBUTE_READONLY, 
    0); //PInvoked too

if (handle.ToInt32() == -1) 
{
    return; 
}

long fileSize;
bool result = GetFileSizeEx(handle, out fileSize);
if (!result) 
{
    return;
}