Come ottenere la dimensione del file in byte con C ++ 17


97

Ci sono insidie ​​per sistemi operativi specifici, dovrei essere a conoscenza?

Ci sono molti duplicati ( 1 , 2 , 3 , 4 , 5 ) di questa domanda ma hanno avuto risposta decenni fa. Le risposte molto alte in molte di queste domande sono oggi sbagliate.

Metodi da altri (vecchi QA) su .sx

  • stat.h (wrapper sprintstatf ), utilizza syscall

  • tellg () , restituisce per definizione una posizione ma non necessariamente byte . Il tipo restituito non è int.



5
@LF: Bene, la prima domanda è stata chiusa come un duplicato della seconda, il che spiega perché la risposta accettata nella prima è sbagliata . La terza domanda riguarda tellgproblemi simili . L'unico di cui vale la pena preoccuparsi è il quarto, e quello non è eccezionale, dal momento che parla troppo ofstream, sia nella domanda che nelle risposte. Questo è di gran lunga migliore nell'esprimere l'intento rispetto agli altri (tranne il primo, che è stranamente chiuso).
Nicol Bolas

6
Smetti di aggiungere informazioni irrilevanti alla tua domanda e al titolo della domanda. L'anno è irrilevante; le tecnologie sono rilevanti.
elixenide

2
Cosa c'è che non va stat(2)comunque? È diventato troppo vecchio o cosa?
Lorinczy Zsigmond

1
@LorinczyZsigmond Cosa c'è che non vastat(2) Non fa parte dello standard linguistico.
Andrew Henle

Risposte:


123

<filesystem>(aggiunto in C ++ 17) lo rende molto semplice .

#include <cstdint>
#include <filesystem>

// ...

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

Come notato nei commenti, se hai intenzione di utilizzare questa funzione per decidere quanti byte leggere dal file, tieni presente che ...

... a meno che il file non venga aperto esclusivamente da te, la sua dimensione può essere modificata tra il momento in cui lo richiedi e il momento in cui provi a leggere i dati da esso.
- Nicol Bolas


11
Poco offtopico: c'è un mondo in cui std::uintmax_tsarà in grado di contenere valori maggiori di std::size_t? In caso contrario, perché non utilizzare std::size_t, quale probabilmente è più riconoscibile? +1 alla risposta, btw
Fureeish

13
@ Fureeish ho usato solo perché questo è il tipo di file_sizeritorno. Anche a me sembra un po 'strano.
HolyBlackCat

39
@Fureeish std::size_tè richiesto solo per contenere la dimensione massima degli oggetti in memoria. I file possono essere notevolmente più grandi,
Richard Critten,

26
@ Fureeish Bene, su Windows a 32 bit (e presumo sulla maggior parte delle moderne piattaforme a size_t32 bit ) è a 32 bit e uintmax_t64 bit.
HolyBlackCat

16
@HolyBlackCat: Sarebbe bene dire qualcosa sul fatto che il filesystem è globale, e quindi a meno che il file non sia aperto esclusivamente da te, la sua dimensione può essere modificata tra il momento in cui lo richiedi e il momento in cui provi a leggere i dati da.
Nicol Bolas

28

C ++ 17 porta std::filesystemche semplifica molte attività su file e directory. Non solo puoi ottenere rapidamente la dimensione del file, i suoi attributi, ma anche creare nuove directory, scorrere i file, lavorare con oggetti percorso.

La nuova libreria ci offre due funzioni che possiamo usare:

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

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

La prima funzione è una funzione libera in std::filesystem, la seconda è un metodo in directory_entry.

Ogni metodo ha anche un sovraccarico, poiché può generare un'eccezione o restituire un codice di errore (tramite un parametro di output). Di seguito è riportato il codice di dettaglio che spiega tutti i casi possibili.

#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
Cos'è esattamente "questo"? Puoi spiegare a cosa serve tutto questo codice, specialmente quando la risposta accettata usa molto meno codice?
Nico Haase
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.