заголовок fstream надає функціонал для зчитування даних з файлу і для запису в файл. В цілому він дуже схожий на хедер iostream, який працює з консоллю, оскільки консоль це теж файл. Тому всі основні операції такі ж, за дрібними відмінностями, як в попередній темі по iostream.
Найбільш часті операції наступне:
- Оператори перенаправлення вводу виводу – << і >>
- Методи запису і читання рядків getline() і get() c ставити()
- Передача потокового запис і читання методами запис() і зчитування()
- Методи відкриття створення і закриття файлів ВІДЧИНЕНО() і близько()
- Методи перевірки чи відкритий файл is_open() і чи досягнуто кінець файлу ВФ()
- Налаштування форматированного виведення для >> за допомогою ширина() і точність()
- операції позиціонування tellg(), tellp() і seekg(), seekp()
Це не всі можливості, які надає бібліотека fstream. Розглядати всі зараз ми не будемо, оскільки їх коло застосування досить вузький. Познайомимося з вищепереліченими. Почнемо з класу читання.
клас ifstream
Надає можливості для читання файлів. Відкрити файл можна двома способами: викликавши метод ВІДЧИНЕНО() або вказавши шлях до нього в конструкторі. Вам необхідно підготувати текстовий файл, перед тем, як почати набирати код. На диску d створіть папку з ім'ям 1 і в ній створіть файл з розширенням txt – “файл.txt”.
1 2 3 4 5 6 7 8 9 | #include <iostream> #include <fstream> // подключаем библиотеку using namespace std; int main() { ifstream file; // создаем объект класса ifstream file.open("d:\\1\\файл.txt"); // открываем файл } |
Відкриття файлу в конструкторі виглядає так:
1 2 3 4 5 6 7 8 | #include <iostream> #include <fstream> // подключаем библиотеку using namespace std; int main() { ifstream file ("d:\\1\\файл.txt"); // открываем файл в конструкторе } |
Так ми просимо відкрити файл txt з ім'ям файл.txt, який лежить в папці з назвою 1, а папка знаходиться на диску d.
Використання методу open() зручно, якщо програміст не хоче відразу прив'язуватися до файлу. Раптом потрібно властивість класу або глобальну змінну, ну а відкривати файл вже потім. Якщо ж потрібно відкрити файл всередині якоїсь функції, попрацювати з ним і закрити, то можна прописати шлях до файлу прямо в конструкторі. Загалом залежить від ситуації.
відкривши файл, бажано прописати перевірку: відкрився він? Так як є ряд причин, за якими файл може не відкритися, а ми цього не побачимо. Наприклад, файлу з вказаним ім'ям немає в прописаної папці або шлях вказано невірно. Можна піти двома шляхами: перевірити змінну файлу влогічному вираженні (застосувавши оператор “!”, наприклад) або використовувати метод is_open() :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | #include <iostream> #include <fstream> using namespace std; int main() { setlocale(LC_ALL, "rus"); ifstream file ("d:\\1\\файл.txt"); if (!file) { cout << "Файл не открыт\n\n"; return -1; } else { cout << "Все ОК! Файл открыт!\n\n"; return 1; } } |
Так все відпрацює нормально і файл відкриється:
Тепер спробуйте вписати назву папки НЕ 1, а 2 ifstream файл ("d:\\<стиль діапазон ="колір: #ff0000;"><сильний>2</сильний>\\файл.txt”); і знову запустіть програму. Так як папки з вказаним ім'ям ми не створювали, то і файл, естественно, не може бути відкритий:
Другий варіант перевірки з використанням методуis_open() :
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | #include <iostream> #include <fstream> using namespace std; int main() { setlocale(LC_ALL, "rus"); ifstream file ("d:\\1\\файл.txt"); if (file.is_open()) // вызов метода is_open() cout << "Все ОК! Файл открыт!\n\n" << endl; else { cout << "Файл не открыт!\n\n" << endl; return -1; } } |
методis_open() вернет 1, якщо файл знайдений і успішно відкритий. інакше поверне 0 і спрацює код прописаний в блоці else.
Якщо файл не відкритий – бажано обробити помилку. Як правило, якщо вся робота програми пов'язана з файлом пишуть якесь повідомлення в консоль, і ставлять вихід з програми. При серйозні помилки прийнято повертати якийсь код виконання (число), який буде характеризувати ту чи іншу помилку. Коди для кожного виду помилок автор програми може придумувати свої. Один із способів обробки помилок в програмі ми розглядали в статті Винятки в С ++.
Якщо файл успішно відкритий, з нього можна зчитувати.
оператор зчитування>>
Так само як і в iostream зчитування можна організувати оператором >>, який вказує в яку змінну буде вироблено зчитування:
1 2 3 4 5 | double d; int i; string s; file >> d >> i >> s; |
вважає речовий, ціле і рядок. Зчитування рядка закінчиться, якщо з'явиться пробіл або кінець рядка. Варто відзначити, що оператор >> застосовується до текстових файлів. Зчитування з бінарного файлу виробляти найкраще за допомогою методу зчитування().
До речі цей оператор досить зручний, якщо стоїть завдання розділити файл на слова:
1 2 3 | // Считка слов из файла for(file >> s; !file.eof(); file >> s) cout << s << endl; |
Методы getline() і отримати()
Зчитування цілого рядка до перекладу каретки проводиться так само як і в iostream методом getline(). Причому рекомендується використовувати його перевизначення версію у вигляді функції, якщо зчитується рядок типу string:
1 2 3 4 | //Считка строки из текста string s; getline(file,s); cout << s << endl; |
Якщо ж читати потрібно в масив символів char[], то або get() либо getline() саме як методи:
1 2 3 4 5 6 7 8 9 10 11 12 | int n = 10; //Создаем буффер для чтения char* buffer = new char[n+1]; buffer[n]=0; //Читаем n символов file.get(buffer,n); //Или так, но до первого пробела file.getline(buffer,n,' '); //выводим считанное cout << buffer; //Освобождаем буффер delete [] buffer; |
Принцип в загальному той же, що і в аналогах з iostream: Вказується в параметрах буфер (переменная, куди буде проводитися читання), або точніше покажчик на блок пам'яті (якщо змінна оголошена статично: буфер символ[255] наприклад, то пишеться в параметри &буфер), вказується максимальна кількість зчитуваного (в прикладі це n), щоб не сталося переповнення і вихід за межі буфера і в разі потреби символ-роздільник, до якого буде зчитування (в прикладі це пробіл). Сподіваюся я не боляче наступлю на хобот фанатикам Сі, якщо сажу що ці дві функції на 99% взаємозамінні, і на 95% можуть бути замінені методом зчитування().
метод зчитування()
1 2 3 4 5 6 7 8 9 | //Считка из файла N байт int n=10; //Создаем буффер char* buffer=new char[n+1]; buffer[n]=0; //Читаем в него байты file.read(buffer,n); //выводим их на экран cout<<buffer; delete [] buffer; |
Схожий на попередній приклад?
Власне тут той же результат – вважається вказану кількість символів. Виняток тільки в тому, що не можна вказати роздільник. зчитування() застосовується для неформатированного введення. Покликаний в першу чергу читати бінарні файли. Оскільки текстовий файл – окремий випадок бінарного, цей метод цілком можна застосувати і до текстового файлу.
метод близько()
закриває файл. Навіть додати нічого. Єдина мабуть ремарка – від того, що файл, відкритий для читання, не буде закритий цим методом як правило гірше не стане. Дуже рідкісні ситуації, коли відкритий для читання файл псується, якщо завершити програму не закриваючи файл. Пов'язана ця псування насамперед з нестандартними пристроями типу стримерів на магнітній стрічці або яких небудь потокових хитрих промислових контролерів, але по феншую варто запам'ятати– відкритий файл повинен бути закритий. Це вважається хорошим тоном.
метод ВФ()
Перевіряє не досягнуть кінець файла. Тобто,. чи можна з нього продовжувати читання. Вище приклад з зчитування слів оператором >> якраз використовує таку перевірку.
метод seekg()
Виробляє установку поточної позиції в потрібну, що вказується числом. У цей метод так само передається спосіб позиціонування:
- ios_base::end – Відрахувати нову позицію з кінця файлу
- ios_base::благати – Відрахувати нову позицію з початку файлу (абсолютне позиціонування)
- ios_base::дворняжка – Перескочити на n байт починаючи від поточної позиції у файлі (по умолчанию)
1 2 3 4 5 | file.seekg(0,ios_base::end); //Стать в конец файла file.seekg(10,ios_base::end); //Стать на 10 байтов с конца file.seekg(30,ios_base::beg); //Стать на 31-й байт file.seekg(3,ios_base::cur); //перепрыгнуть через 3 байта file.seekg(3); //перепрыгнуть через 3 байта - аналогично |
метод tellg()
Іноді потрібно отримувати інформацію про те, скільки вже прочитано. У цьому допоможе метод tellg():
1 | cout << "Считано байт: " << file.tellg(); |
Він повертає значення типу int, яке показує скільки вже пройдено в байтах. Його можна використовувати в парі з методом seekg(), щоб отримувати розмір файлу:
1 2 3 4 | //становимся в конец файла file.seekg(0,ios_base::end); //Получаем текущую позицию cout << "Размер файла (в байтах): " << file.tellg(); |
Як приклад роботи методів бінарного читання можна розібрати такий класс:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 | class ReadStream { private: //Приватное поле - файл ifstream f; public: //Конструктор, открывающий файл ReadStream(const char *FileName){ f.open(FileName); if(!f.is_open()) cout<<"Файл не открыт"; } //Метод чтения массива символов-байт с указанной позиции //который возвращает этот массив char *read(int position, int count){ if(!f.is_open()) return 0; f.seekg(position); if(f.eof()) return 0; char *buffer=new char[count]; f.read(buffer,count); return buffer; } //Деструктор, закрывающий файл ~ReadStream(){ f.close(); } }; |
Подібні обгортки-класи зручно використовувати, якщо зустрічається завдання читати з бінарного файлу цілі структури.
Відео про роботу з файлами в С ++:
f.seekg(9, ios_base::end);
f.read(ч,8);
розмір файлу (в байтах): -1Для продовження натисніть будь-яку клавішу . . .
Що на рахунок методу .seekp()? він по ідеї теж відповідає за якийсь покажчик, а тут інформації немає……
Ну і код-стайл, млинець. Всі блоки і аргументи наліплені один на інший, ні прогалин, ні табуляції, в ReadStream тільки, хоча, підозрюю, звідти шматок був просто акуратненько вкрадений. Благо хоч сама писанина НЕ бидлокод…
+++аналогічну думку: дизайн веб-сайту чудовий, оформлення коду – г…але!
думаю, считку слів з файлу краще реалізовувати через do … while, ніж через for.
do {
файл >> s;
cout << s << endl;
} while (!file.eof());
Вибір оператора циклу залежить від знання про кількість ітерацій: якщо кількість невідома – тоді краще застосовувати WHILE, якщо відомо – рекомендується FOR (читав в Полякова До. Ю., підручник поглибленого рівня).
Оооочень мало інформації. думаю, десь між 1 і 2 % від загальних можливостей ЯП “C / C ++”. У нас на лекція в інституті зовсім про інші методи розповідають, набагато більш коротких і зручних. Ось дещо з них:
Різниця між цими двома методами полягає в тому, що getline () витягує з потоку обмежує символ (\0), в той час як get () цього не робить. ні той, ні інший метод не записує обмежує символ в буфер.
Цикл For класно зроблений)
if (!файл)
{
cout << "Файл не открыт\n\n";
return -1;
}
Вітаю, а навіщо в конструкції if оператор return??? для чого він? що він робить у цьому прикладі?
Завершення функції, у даному випадку функції main.
Може ви напишіть щось про створення файлів під час виконання коду і про те як з ними працювати якщо не знаєш точної папки(у мене, наприклад, взагалі немає диска “d” і цей код у мене не запрацює)