С++ файловый поток открытые режимы неоднозначность - программирование
Подтвердить что ты не робот

С++ файловый поток открытые режимы неоднозначность

Для выполнения IO файла в С++ мы используем классыstream, ifstream и fstream.

  • ofstream: класс Stream для записи в файлах
  • ifstream: класс Stream для чтения из файлов
  • fstream: класс Stream для чтения и записи из/в файлы

Процесс связывания файла с объектом потока называется "открытием файла". При открытии файла мы можем указать режим, в котором файл должен быть открыт. Мой запрос связан с режимами ios::out и ios:in.

Когда я создаю объект ofstream и открываю файл в режиме ios::in, я могу пишите в файл, но только если его уже создано (с файлом режима ios::out также создается, если он еще не существует).
Но когда я создаю объект ifstream и открываю файл в режиме ios::out, я могу читать из файла.

Мой вопрос в том, почему эти режимы (ios::in/ios::out) предоставляются языком, когда сам тип потока (ifstream/ofstream) указывает, какой тип операции (ввод/вывод) ) выполняется?

Также почему это неоднозначное использование (ofstream с ios::in и ifstream с ios::out) работает в одном случае и не удается (хотя только если файл еще не присутствует) в другом?

4b9b3361

Ответ 1

Классы ofstream, ifstream и fstream - это интерфейсы высокого уровня для подстроки filebuf, которые можно получить через функцию члена rdbuf() для потока.

В соответствии со стандартом, когда вы открываете ofstream с некоторым режимом mode, он открывает буфер подчеркивания потока, как и в mode | ios_base::out. Аналогично ifstream использует mode | ios_base::in. fstream передает параметр mode дословно в буфер потока подчеркивания.

Из сказанного следует, что следующий код открывает файл с точно такими же открытыми флагами:

fstream f("a.txt", ios_base::in | ios_base::out);
ifstream g("a.txt", ios_base::out);
ofstream h("a.txt", ios_base::in);

После этих строк вы можете делать то же самое с f.rdbuf(), g.rdbuf() и h.rdbuf(), и все три действуют так, как будто вы открыли файл с помощью вызова C fopen("a.txt", "r+"), который дает вам чтение/доступ на запись, не обрезает файл и не удается, если файл не существует.

Итак, почему у нас есть три разных класса? Как я уже сказал, это классы высокого уровня, обеспечивающие высокоуровневый интерфейс над потоковым буфером более низкого уровня. Идея состоит в том, что ifstream имеет функции-члены для ввода (например, read()), ofstream имеет функции-члены для вывода (например, write()), а fstream - оба. Например, вы не можете этого сделать:

g.write("abc", 3); // error: g does not have a write function

Но это работает, потому что, хотя g является ifstream, мы открыли его с помощью ios_base::out:

g.rdbuf()->sputn("abc", 3); // we still have write access

Ответ 2

Поскольку режим не ограничивается вводом/выводом. Например, конструктор ifstream выглядит следующим образом:

explicit ifstream ( const char * filename, ios_base::openmode mode = ios_base::in );

Обратите внимание, что значение по умолчанию ios_base::in, поэтому вам не нужно указывать его самостоятельно. Однако mode устанавливает флаги потоков не, ограниченные in/out, но включают:

  • app (добавить) Установите индикатор позиции потока в конец потока перед каждой операцией вывода.
  • ate (в конце) Установите индикатор положения потока в конец потока при открытии.
  • binary (двоичный) Рассмотрим поток как двоичный, а не текстовый.
  • in (ввод) Разрешить операции ввода в потоке.
  • out (вывод) Разрешить выходные операции в потоке.
  • trunc (truncate) Любое текущее содержимое отбрасывается, предполагая длину нуля при открытии.