วิธีรับขนาดไฟล์เป็นไบต์ด้วย C ++ 17


98

มีข้อผิดพลาดสำหรับระบบปฏิบัติการเฉพาะที่ฉันควรรู้หรือไม่?

คำถามนี้มีคำซ้ำหลายรายการ ( 1 , 2 , 3 , 4 , 5 ) แต่ได้รับคำตอบเมื่อหลายสิบปีก่อน คำตอบที่ได้รับการโหวตสูงมากในหลายคำถามเหล่านี้ผิดในปัจจุบัน

วิธีการจากอื่น ๆ (QA เก่า) บน. sx

  • stat.h (wrapper sprintstatf ) ใช้ syscall

  • tellg ()ผลตอบแทนต่อความหมายตำแหน่งแต่ไม่จำเป็นต้องไบต์ intประเภทผลตอบแทนไม่ได้


4
เริ่มต้นสำหรับ 10: en.cppreference.com/w/cpp/header/filesystem
Richard Critten

5
@LF: ดีคำถามแรกที่ได้รับการปิดเป็นซ้ำครั้งที่สองซึ่งจะอธิบายว่าทำไมคำตอบที่ได้รับการยอมรับในครั้งแรกเป็นสิ่งที่ผิด อันที่สามกำลังถามเกี่ยวกับtellgปัญหาที่คล้ายกัน สิ่งเดียวที่ควรค่าแก่การรบกวนคือข้อที่สี่และสิ่งนั้นไม่ดีนักเนื่องจากพูดถึงมากเกินไปofstreamทั้งในคำถามและคำตอบ อันนี้ดีกว่าในการแสดงเจตนามากกว่าคนอื่น ๆ (ยกเว้นครั้งแรกที่ปิดแบบแปลก ๆ )
Nicol Bolas

6
โปรดหยุดเพิ่มข้อมูลที่ไม่เกี่ยวข้องในคำถามและชื่อคำถามของคุณ ปีไม่เกี่ยวข้อง เทคโนโลยีมีความเกี่ยวข้อง
elixenide

2
มีอะไรผิดปกติstat(2)? มันโตเกินไปหรืออะไร?
Lorinczy Zsigmond

1
@LorinczyZsigmond มีอะไรผิดปกติstat(2) มันไม่ได้เป็นส่วนหนึ่งของมาตรฐานภาษา
Andrew Henle

คำตอบ:


124

<filesystem>(เพิ่มใน C ++ 17) นี้จะทำให้ตรงไปตรงมามาก

#include <cstdint>
#include <filesystem>

// ...

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

ตามที่ระบุไว้ในความคิดเห็นหากคุณวางแผนที่จะใช้ฟังก์ชั่นนี้เพื่อตัดสินใจว่าจะอ่านไฟล์จำนวนกี่ไบต์โปรดทราบว่า ...

... เว้นแต่คุณจะเปิดไฟล์โดยเฉพาะขนาดของไฟล์สามารถเปลี่ยนแปลงได้ระหว่างเวลาที่คุณขอและเวลาที่คุณพยายามอ่านข้อมูลจากไฟล์
- นิโคลโบลาส


11
Little offtopic: มีโลกไหนบ้างที่std::uintmax_tจะสามารถรักษาคุณค่าที่ยิ่งใหญ่ไปกว่านี้ได้std::size_t? ถ้าไม่ทำไมไม่ใช้std::size_tเนื้อหาใดที่เป็นที่รู้จักมากกว่า +1 ในคำตอบ btw
Fureeish

13
@Fureeish ฉันใช้เพียงเพราะนั่นคือfile_sizeผลตอบแทนประเภท ดูแปลก ๆ สำหรับฉันด้วย
HolyBlackCat

39
@Fureeish std::size_tจำเป็นต้องมีขนาดสูงสุดของวัตถุในหน่วยความจำเท่านั้น ไฟล์อาจมีขนาดใหญ่กว่ามาก
Richard Critten

27
@Fureeish Well บน Windows 32 บิต (และฉันคิดว่าบนแพลตฟอร์มsize_t32 บิตที่ทันสมัยที่สุด) คือ 32 บิตและuintmax_tเป็น 64 บิต
HolyBlackCat

16
@HolyBlackCat: มันจะเป็นการดีที่จะพูดอะไรบางอย่างเกี่ยวกับความจริงที่ว่าระบบไฟล์เป็นแบบสากลดังนั้นหากคุณไม่เปิดไฟล์โดยเฉพาะขนาดของไฟล์สามารถเปลี่ยนแปลงได้ระหว่างเวลาที่คุณขอและเวลาที่คุณพยายามอ่านข้อมูล จากมัน.
Nicol Bolas

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
"นี่" คืออะไรกันแน่? คุณช่วยอธิบายได้ไหมว่ารหัสทั้งหมดนี้ใช้สำหรับอะไรโดยเฉพาะเมื่อคำตอบที่ยอมรับนั้นใช้รหัสน้อยกว่ามาก
Nico Haase
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.