2017-01-18 3 views
2
#include <fstream> 
#include <string> 
#include <cassert> 

long long GetFileSizeA(const std::string& file_path) 
{ 
    return std::ifstream 
    { 
     file_path, std::ios::ate  
    }.tellg(); 
} 

long long GetFileSizeB(const std::string& file_path) 
{ 
    return std::ifstream 
    { 
     file_path, std::ios::ate | std::ios::binary 
    }.tellg(); 
} 

int main() 
{ 
    auto a = GetFileSizeA("~/test.log"); 
    auto b = GetFileSizeB("~/test.log"); 

    assert(a == b); // always true? 
} 

Если файл ~/test.log содержит много \r\n последовательности, делает C++ стандартной гарантии GetFileSizeA идентична GetFileSizeB?Должен ли я открыть файл в режиме [ios :: binary], чтобы получить его размер?

ответ

1

Стандарт делает отнюдь не гарантирует, что они равны (и не делает C или C++ стандартного состояния содержат ли файлы \r\n или \n или \r как линия заканчивается, что определяется операционной системой и/или приложением. Стандартная библиотека C и, соответственно, библиотека C++, гарантируют, что если вы прочитаете файл в текстовом режиме, он преобразует любые фактические окончания строки во внутреннюю форму \n). Это также не гарантирует, что это НЕ то же самое значение всегда.

Что еще более важно, вы вполне можете обнаружить, что если вы прочитаете часть файла и спросите «где я», ответ будет другим, если вы читаете как двоичный файл или как файл ascii. Если вы планируете, например, отображать файл в память и обрабатывать его как большую строку символов, без перевода строк новой строки, вам нужно сделать это как двоичный файл.

1

Нет такой гарантии по стандарту C++.

В самом деле, код

std::ifstream{file_path, std::ios::ate | std::ios::binary}.tellg(); 

не гарантированно работать, как задумано, либо. Операция tellg() на потоках, основанных на файлах, сжимается через пару промежуточных функций (std::basic_istream::tellg ->std::basic_streambuf::pubseekoff ->std::basic_filebuf::seekoff) и с использованием формулировки «, как будто», до std::fseek(). Последнее isn't required to support seeking in binary streams relative to the end position:

int fseek(std::FILE* stream, long offset, int origin);

Устанавливает индикатор позиции файла для потока файла потока.

Если поток открыт в двоичном режиме, новое положение точно смещение байтов, измеренных с начала файла, если происхождение SEEK_SET, от текущей позиции файла, если происхождение SEEK_CUR, и с конца файл, если источник - SEEK_END. Бинарные потоки не обязательны для поддержки SEEK_END, в частности, если выводятся нулевых байтов.

Смежные вопросы