Як отримати розмір файлу в байтах за допомогою C ++ 17


97

Чи я маю знати підводні камені для конкретних операційних систем?

Існує багато дублікатів ( 1 , 2 , 3 , 4 , 5 ) цього питання, але на них відповіли десятки років тому. На сьогодні дуже багато відповідей у ​​багатьох із цих питань є помилковими.

Методи з інших (старих QA) на .sx

  • stat.h (обгортка sprintstatf ), використовує syscall

  • Tellg () , повертає за визначенням позицію, але не обов'язково байти . Тип повернення не є int.



5
@LF: Ну, перше питання було закрито як дублікат другого, що пояснює, чому прийнята відповідь у першому є неправильною . Третій запитує про подібні tellgпроблеми. Єдиний, з ким варто потурбуватись, - це четвертий, і той не є чудовим, оскільки йдеться надто багато ofstreamяк у питанні, так і в його відповідях. Цей набагато краще виражає намір, ніж інші (за винятком першого, який дивним чином закритий).
Nicol

6
Будь ласка, припиніть додавати неактуальну інформацію до свого запитання та назви запитання. Рік не має значення; технології актуальні.
elixenide

2
Що stat(2)взагалі не так? Чи занадто воно постаріло чи що?
Lorinczy Zsigmond

1
@LorinczyZsigmond Що поганого,stat(2) це не є частиною мовного стандарту.
Ендрю Генле,

Відповіді:


123

<filesystem>(додано в C ++ 17) робить це дуже просто .

#include <cstdint>
#include <filesystem>

// ...

std::uintmax_t size = std::filesystem::file_size("c:\\foo\\bar.txt");

Як зазначалося в коментарях, якщо ви плануєте використовувати цю функцію, щоб визначити, скільки байт читати з файлу, майте на увазі, що ...

... якщо файл не відкритий виключно вами, його розмір можна змінювати між часом, коли ви просите його, і часом, коли ви намагаєтесь прочитати з нього дані.
- Нікол Болас


11
Невелика офтопіка: чи існує світ, де std::uintmax_tможна буде тримати більші цінності, ніж std::size_t? Якщо ні, чому б не використовувати std::size_t, що, мабуть, є більш впізнаваним? +1 на відповідь, до речі
Fureeish

13
@Fureeish я використовував лише тому, що такий тип file_sizeповертається. Мені теж виглядає трохи дивно.
HolyBlackCat

39
@Fureeish std::size_tпотрібен лише для розміщення максимального розміру в об'єктах пам'яті. Файли можуть бути значно більшими,
Річард Криттен,

26
@Fureeish Ну, для 32-розрядної Windows (і я припускаю, на більшості сучасних 32-розрядних платформ) size_tце 32 біти, і uintmax_tце 64 біти.
HolyBlackCat

16
@HolyBlackCat: Було б добре сказати щось про те, що файлова система є глобальною, і, отже, якщо файл не відкритий виключно вами, його розмір можна змінювати між часом, коли ви просите його, і часом, коли ви намагаєтесь прочитати дані з цього.
Nicol

28

C ++ 17 пропонує, std::filesystemщо впорядковує багато завдань щодо файлів та каталогів. Ви не тільки можете швидко отримати розмір файлу, його атрибути, а й створити нові каталоги, перебирати файли, працювати з об’єктами шляху.

Нова бібліотека дає нам дві функції, якими ми можемо користуватися:

std::uintmax_t std::filesystem::file_size( const std::filesystem::path& p );

std::uintmax_t std::filesystem::directory_entry::file_size() const;

Перша функція - це вільна функція в std::filesystem, друга - метод у directory_entry.

Кожен метод також має перевантаження, оскільки може викликати виняток або повернути код помилки (через вихідний параметр). Нижче наведено детальний код, що пояснює всі можливі випадки.

#include <chrono>
#include <filesystem>  
#include <iostream>

namespace fs = std::filesystem;

int main(int argc, char* argv[])
{
    try
    {
        const auto fsize = fs::file_size("a.out");
        std::cout << fsize << '\n';
    }
    catch (const fs::filesystem_error& err)
    {
        std::cerr << "filesystem error! " << err.what() << '\n';
        if (!err.path1().empty())
            std::cerr << "path1: " << err.path1().string() << '\n';
        if (!err.path2().empty())
            std::cerr << "path2: " << err.path2().string() << '\n';
    }
    catch (const std::exception& ex)
    {
        std::cerr << "general exception: " << ex.what() << '\n';
    }

    // using error_code
    std::error_code ec{};
    auto size = std::filesystem::file_size("a.out", ec);
    if (ec == std::error_code{})
        std::cout << "size: " << size << '\n';
    else
        std::cout << "error when accessing test file, size is: " 
              << size << " message: " << ec.message() << '\n';
}

2
Що саме таке "це"? Чи можете ви пояснити, для чого використовується весь цей код, особливо коли прийнята відповідь використовує значно менше коду?
Ніко Хаасе,
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.