Определение размера файла с помощью процедуры CRT

#c #windows

#c #Windows

Вопрос:

Итак, в настоящее время я использую этот код для открытия указанного файла:

 FILE* stream;
stream = fopen("file.txt", "w ");
 

Моя цель — получить размер этого файла, но я не смог найти какую-либо явную функцию, которая определяла бы размер файла в библиотеке времени выполнения CRT.

Я нашел только GetFileSize or GetFileSizeEx , но эти функции находятся в fileapi заголовочном файле и используют дескрипторы вместо потоков, что означает, что мне нужно будет написать большой кусок кода только для размера файла (открытие файла, проверка достоверности, получение размера файла с помощью дескриптора, закрытие дескриптора), что приведет к дополнительным накладным расходам.

Есть идеи о том, как я мог бы сделать это с помощью процедуры CRT (например, той, которая начинается с f префикса)?

Комментарии:

1. docs.microsoft.com/en-us/cpp/c-runtime-library/reference/…

2. Вы можете использовать stat с путем, если хотите. На обеих связанных страницах есть примеры. docs.microsoft.com/en-us/cpp/c-runtime-library/reference /…

3. Для чего это стоит, если вы планируете открыть файл в w режиме, размер всегда будет равен 0, поскольку это уничтожает содержимое. en.cppreference.com/w/cpp/io/c/fopen

Ответ №1:

Типичный способ получить размер FILE* потока — это перейти fseek() к концу потока, а затем ftell() к позиции, которая была фактически просмотрена.

Обратите внимание, что поток должен быть открыт в обычном "b" режиме, чтобы отключить переводы разрывов строк, которые могут изменить позицию.

 FILE* stream;
stream = fopen("file.txt", "rb");
fseek(stream, 0, SEEK_END);
long size = ftell(stream);
...
 

Комментарии:

1. Обратите внимание, что это не удается для файлов размером 2 ГБ и больше. Стандартная библиотека C, основанная на POSIX, в значительной степени бесполезна, когда дело доходит до ввода-вывода файлов. Реализация CRT от Microsoft обеспечивает смягчающие меры, такие как _ftelli64 и _fseeki64 .

Ответ №2:

Это то, что я придумал, однако способ @Remy Lebeau также работает.

 struct _stat fd;
if(_fstat(_fileno(stream), amp;fd) != 0)
        return -1;
DWORD fsize =  fd.st_size;
 

Ответ №3:

Попробуйте это:

 size_t fileSize(const char* fileName)
{
    ifstream ifs;
    size_t len;

    ifs.open(fileName, ifstream::binary);
    ifs.seekg(0, ios::end);     // go to the end
    len = (size_t)ifs.tellg();  // report length
    ifs.close();
    return len;
}
 

Комментарии:

1. Это можно немного упростить, используя ifstream конструктор для открытия и поиска потока за одну операцию и позволяя деструктору закрывать поток, когда он выходит за рамки, например: size_t fileSize(const char* fileName) { return ifstream(fileName, ifstream::binary | ifstream::ate).tellg(); }

Ответ №4:

Есть хороший способ сделать это на C 17:

 #include <iostream>
#include <filesystem>

int main()
{
    namespace fs = std::filesystem;
    std::cout << "File size = " << fs::file_size("path_to_file");
    return {};        
}
 

Дополнительная информация здесь https://en.cppreference.com/w/cpp/filesystem/file_size