16-06-2005 18:45 Сиплюплюсное
почему

ifstream file(filename);
while (!file.eof()) {
	cout<<file.get();
}


печатает не весь файл, если файл не текстовый?
Убил на это два часа. В конце концов плюнул и сделал fopen(filename, "rb")
Комментарии:
17-06-2005 00:05
Камрад с блокнотиком
В файле где-нибудь встречается признак конца и/или нулевой символ.

std::ifstream file(filename, std::ios_base::binary);
std::copy(std::istreambuf_iterator<char>(file), std::istreambuf_iterator<char>(),
  std::ostream_iterator<char>(std::cout));
17-06-2005 00:15
Камрад
Спасибо. Интересно, что
ifstream file(filename);
while (1) {
	cout<<file.get();
}

печатает до первого символа конца файла (-1), а потом печатает только этот символ, не проходя файл до конца.
Я не понимаю, как это внутри устроено. Почему это не работает, а другие методы работают, хотя вроде бы то же самое.
FILE * F= fopen(filename, "rb");
while( !feof(F) ) {
     cout<<getc(F);
}

сработало
Он как-то по разному работает с двоичными и текстовыми файлами?
18-06-2005 11:30
Камрад с блокнотиком
while (1) — это бесконечный цикл.

get() при достижении логического конца файла выставляет бит (std::ios_base::eofbit) и не продвигается за признак конца.

Представление символа конца файла определяется платформой, на DOS/Windows это (char)0x1A.

ifstream можно заставить бросать exception по достижении конца файла:
file.exceptions(std::ios_base::eofbit);


Двоичный файл — это поток символов, без обработки. Текстовый файл — это поток символов, разделённый на строки. При переходе с одной строки на другую поток отдаст символ '\n', в то время как в текстовом файле в DOS/Windows этот переход представлен двумя символами 0x0D 0x0A, на Mac’ах — 0x0A 0x0D, а в UNIX-подобных системах — одним 0x0D. Аналогично, при выводе в текстовый поток '\n' транслируется в платформозависимое представление конца строки.

Отсюда, в частности, следует ещё одно различие между текстовыми и двоичными потоками и файлами: в двоичных можно позиционироваться (seekg, seekp) на любое смещение от начала, конца и текущей позиции, а в текстовых — только от начала и только на те смещения, которые до этого были запомнены с помощью tellg или tellp.

Последний пример в C++ будет выглядеть так:
std::ifstream f(filename, std::ios_base::binary);
while (!f.eof())
{
  std::cout << f.get();
}
Закрыть