Cara mendapatkan ukuran file dalam byte dengan C ++ 17


97

Apakah ada kendala untuk sistem operasi tertentu, yang harus saya ketahui?

Ada banyak duplikat ( 1 , 2 , 3 , 4 , 5 ) dari pertanyaan ini tetapi sudah dijawab beberapa dekade yang lalu. Jawaban yang sangat dipilih dalam banyak pertanyaan ini salah hari ini.

Metode dari lain (QA lama) di .sx

  • stat.h (wrapper sprintstatf ), menggunakan syscall

  • tellg () , mengembalikan per definisi posisi tetapi tidak harus byte . Jenis pengembalian tidak int.



5
@LF: Ya, pertanyaan pertama telah ditutup sebagai duplikat dari pertanyaan kedua, yang menjelaskan mengapa jawaban yang diterima di pertanyaan pertama salah . Yang ketiga menanyakan tentang tellgmasalah yang serupa . Satu-satunya yang perlu diganggu adalah yang keempat, dan yang satu itu tidak hebat, karena terlalu banyak membicarakan ofstream, baik dalam pertanyaan maupun jawabannya. Yang ini jauh lebih baik dalam mengungkapkan maksud daripada yang lain (kecuali yang pertama, yang anehnya ditutup).
Nicol Bolas

6
Harap berhenti menambahkan informasi yang tidak relevan ke pertanyaan Anda dan judul pertanyaan. Tahun tidak relevan; teknologinya relevan.
elixenide

2
Ada apa sih stat(2)? Apakah sudah terlalu tua atau apa?
Lorinczy Zsigmond

1
@LorinczyZsigmond Apa yang salah denganstat(2) Ini bukan bagian dari standar bahasa.
Andrew Henle

Jawaban:


123

<filesystem>(ditambahkan di C ++ 17) membuat ini sangat mudah .

#include <cstdint>
#include <filesystem>

// ...

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

Seperti disebutkan dalam komentar, jika Anda berencana menggunakan fungsi ini untuk memutuskan berapa banyak byte yang akan dibaca dari file, perlu diingat bahwa ...

... kecuali file dibuka secara eksklusif oleh Anda, ukurannya dapat diubah antara waktu Anda memintanya dan waktu Anda mencoba membaca data darinya.
- Nicol Bolas


11
Sedikit offtopic: adakah dunia di mana std::uintmax_takan dapat menyimpan nilai-nilai lebih dari std::size_t? Jika tidak, mengapa tidak digunakan std::size_t, yang bisa dibilang lebih dikenali? +1 pada jawabannya, btw
Fureeish

13
@Fureeish saya gunakan hanya karena itulah tipe file_sizepengembalian. Terlihat agak aneh juga bagiku.
HolyBlackCat

39
@Fureeish std::size_thanya diperlukan untuk menampung ukuran maksimal dalam objek memori. File bisa jauh lebih besar,
Richard Critten

27
@Fureeish Nah, pada Windows 32-bit (dan saya berasumsi pada sebagian besar platform 32-bit modern) size_tadalah 32 bit, dan uintmax_t64 bit.
HolyBlackCat

16
@HolyBlackCat: Sebaiknya katakan sesuatu tentang fakta bahwa sistem file bersifat global, dan dengan demikian, kecuali jika file dibuka secara eksklusif oleh Anda, ukurannya dapat diubah antara saat Anda memintanya dan waktu Anda mencoba membaca data dari itu.
Nicol Bolas

28

C ++ 17 menghadirkan std::filesystemyang menyederhanakan banyak tugas pada file dan direktori. Tidak hanya Anda dapat dengan cepat mendapatkan ukuran file, atributnya, tetapi juga membuat direktori baru, melakukan iterasi melalui file, bekerja dengan objek jalur.

Perpustakaan baru memberi kita dua fungsi yang bisa kita gunakan:

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

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

Fungsi pertama adalah fungsi bebas di std::filesystem, yang kedua adalah metode masuk directory_entry.

Setiap metode juga memiliki kelebihan beban, karena dapat memunculkan pengecualian atau mengembalikan kode kesalahan (melalui parameter keluaran). Di bawah ini adalah kode detail yang menjelaskan semua kemungkinan kasus.

#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
Apa sebenarnya "ini"? Bisakah Anda menjelaskan untuk apa semua kode ini digunakan, terutama ketika jawaban yang diterima menggunakan lebih sedikit kode?
Nico Haase
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.