ifstream против fread для бинарных файлов

Что быстрее? ifstream или fread.
Что следует использовать для чтения двоичных файлов?

fread() помещает в память весь файл.
Таким образом, после fread доступ к созданному буферу происходит быстро.

Помещает ли ifstream::open() весь файл в память?
или он обращается к жесткому диску каждый раз, когда мы запускаем ifstream::read()?

Итак... ifstream::open() == fread()?
или (ifstream::open(); ifstream::read(file_length);) == fread()?

Или мне использовать ifstream::rdbuf()->read()?

Изменить: Мой метод readFile() теперь выглядит примерно так:

void readFile()
{
    std::ifstream fin;
    fin.open("largefile.dat", ifstream::binary | ifstream::in);
    // in each of these small read methods, there are at least 1 fin.read()
    // call inside.
    readHeaderInfo(fin);
    readPreference(fin);
    readMainContent(fin);
    readVolumeData(fin);
    readTextureData(fin);
    fin.close();
}

Будут ли многочисленные вызовы fin.read() в малых методах замедлять работу программы? Должен ли я использовать только 1 fin.read() в основном методе и передавать буфер в маленькие методы? Думаю, я собираюсь написать небольшую программу для тестирования.

Спасибо!


person Snowfish    schedule 25.05.2011    source источник
comment
Что вам нужно сделать, так это написать две программы, по одной для каждого метода, и посмотреть, какая из них быстрее. Используйте большой файл.   -  person Björn Pollex    schedule 26.05.2011
comment
На некоторых платформах есть функции для обращения с файлом как с памятью либо путем чтения содержимого в память, либо путем простого доступа к файлу, как к памяти. Найдите в Интернете файл памяти.   -  person Thomas Matthews    schedule 26.05.2011
comment
В худшем случае несколько операций чтения выполняются медленнее, чем одно большее чтение. Обычной практикой является выделение большого буфера (в динамической памяти), чтение большого количества данных в буфер, а затем его разбор. Эту производительность следует измерять, поскольку некоторые производители операционных систем и дисководов в любом случае буферизуют большие объемы данных, чтобы упростить доступ к ним в будущем.   -  person Thomas Matthews    schedule 26.05.2011


Ответы (5)


Вы действительно уверены, что fread поместите весь файл в память? Доступ к файлу можно буферизовать, но я сомневаюсь, что вы действительно помещаете в память весь файл. Я думаю, что ifstream::read просто использует fread под капотом более совместимым с C++ способом (и, следовательно, это стандартный способ чтения двоичной информации из файла в C++). Сомневаюсь, что есть существенная разница в производительности.

Чтобы использовать fread, файл должен быть открыт. Он не берет просто файл и сразу помещает его в память. так что ifstream::open == fopen и ifstream::read == fread.

person Christian Rau    schedule 25.05.2011
comment
Он вытянет весь файл в память, если вы скажете ему об этом и если он сможет. А когда дело доходит до ввода-вывода, сомневаетесь ли вы в наличии разницы в производительности или нет, это ни здесь, ни там — единственное, что нужно сделать, это измерить ее. - person ; 26.05.2011
comment
@Neil Как вы скажете ему, запросить размер файла и прочитать блок всего размера? Вы можете сделать это и с ifstream. - person Christian Rau; 26.05.2011
comment
Да, вы можете сделать это с обоими? И так? - person ; 26.05.2011
comment
Я думаю, ОП думал, что он просто берет файл и целиком помещает его в память. Но это просто неправильно, fread и ifstream::read выполняют одну и ту же функцию, и ваш комментарий не очень помог ему прояснить это. - person Christian Rau; 26.05.2011
comment
Откуда вы знаете, что ваш комментарий на самом деле не помог ему прояснить это? - person ; 26.05.2011
comment
@Neil Надеюсь, я закончу эту дискуссию сейчас. Я просто имел в виду, что нельзя говорить полуправду. Конечно, fread может прочитать весь файл, но ifstream::read может сделать то же самое. И я знаю, что всегда можно и нужно измерять вещи, поэтому я сказал сомневаюсь и не знаю. - person Christian Rau; 26.05.2011
comment
Спасибо! Теперь я понимаю, что ifstream::read == fread. Но затем я понял свой истинный вопрос из вашего ответа: должен ли я ifstream::read один раз и передать буфер, или ifstream::open и передать ifstream вокруг, чтобы иметь несколько ifstream::read. - person Snowfish; 26.05.2011

Потоковый API С++ обычно немного медленнее, чем API файла C, если вы используете высокоуровневый API, но он обеспечивает более чистый/безопасный API, чем C. Если вам нужна скорость, рассмотрите возможность использования файлов с отображением памяти, хотя переносимого способа сделать это нет. со стандартной библиотекой.

person Nekuromento    schedule 25.05.2011

Что быстрее, смотрите мой комментарий. Что касается прочего:

  • Ни один из этих методов не считывает весь файл в память автоматически. Они оба читают столько, сколько вы укажете.
  • По крайней мере, для ifstream я уверен, что ввод-вывод буферизован, поэтому не обязательно будет доступ к диску для каждого чтения, которое вы делаете.
  • См. этот вопрос для C++-способа чтения двоичных файлов.
person Björn Pollex    schedule 25.05.2011
comment
Спасибо за ответ, я увидел вопрос. Проблема в том, что метод read() был написан кем-то другим. Он ifstream::open() файл в основном методе чтения и передает ifstream в небольшие методы readContent(), внутри которых есть fin.read(). Поэтому я запутался, если мне следует объединить fin.read() в 1 большой fin.read() и передать буфер маленьким методам. - person Snowfish; 26.05.2011
comment
@Snowfish: я не уверен, что понимаю. Я думаю, было бы лучше, если бы вы опубликовали это как отдельный вопрос и показали код, который у вас есть. - person Björn Pollex; 26.05.2011

Идея с файловыми потоками C++ заключается в том, что часть или весь файл буферизуется в памяти (в зависимости от того, что он считает оптимальным), и вам не нужно об этом беспокоиться.

Я бы использовал ifstream::read() и просто сказал, сколько вам нужно.

person Steve Blackwell    schedule 25.05.2011
comment
К сожалению, в зависимости от того, что он считает оптимальным, обычно не достигается оптимальная производительность. - person ; 26.05.2011

Используйте оператор потока:

DWORD processPid = 0;
std::ifstream myfile ("C:/Temp/myprocess.pid", std::ios::binary);
if (myfile.is_open())
{
    myfile >> processPid;
    myfile.close();
    std::cout << "PID: " << processPid << std::endl;
}
person zuko    schedule 15.07.2014