Глава 21
Вверх
Почти все программы занимаются тем, что принимают одни данные и возвращают
Вверх
Запись в потоковый файл осуществляется посредством вызова метода Write:
Записав в файл всю необходимую информацию, закройте поток с помощью метода
Подобным образом осуществляется чтение из файла посредством использования объекта класса StreamReader:
Чтобы получить доступ к пространству имен System.IO, наберите в начале программы такой код:
Вверх
В этом разделе рассматривается пример программы, в процессе выполнения которой вначале в файлы записываются текстовые и числовые данные, а затем те же данные считываются
//Открытие другого файла для записи числовых данных
Затем считываются данные из второго файла. Обратите внимание, что в файле содержится несколько значений. Метод ReadLine, достигнув конца файла, возвращает нулевое значение, что дает возможность использовать цикл while для того, чтобы прочитать из файла
все данные. (О циклах while речь идет в главе ! 1.)
Функции библиотеки iostream
В библиотеке iostream содержится ряд функций, которые помогут записать данные в файл
Специальный класс ofstream предназначен для передачи файлам выходных данных. (Буквы O и I взяты от слов output и files. Слово stream переводится как поток — термин, которым в C++ обозначаются объекты, предназначенные для организации процесса ввода-вывода данных.) В данном случае foo является потоковой переменной (объектом класса ofstream). При создании объекта foo конструктору класса ofstream передается имя файла, который должен быть открыт. Передача данных осуществляется с помощью оператора <<:
Класс ofstream имеет близнеца— класс ifstream, который предназначен для организации процесса чтения данных из файлов. (Здесь буквы i и/обозначают слова input и files.)
Числовая информация считывается несколько иначе:
Да, и самое важное! Перед тем как использовать все эти возможности, нужно подключить
Вверх
Когда потоковая переменная прекращает свое существование, представляемый ею файл закры-
Обычно это делается в тех случаях, когда хотят одну и ту же потоковую переменную использовать для доступа к нескольким файлам. Чтобы сделать это, нужно вначале закрыть один файл, а затем с помощью функции-члена open открыть другой:
Если хотите проверить, осталась ли еще в файле какая-то непрочитанная информация, используйте функцию-член eof, которая возвращает значение true (Истина) в момент достижения окончания файла.
Вверх
Не волнуйтесь, это не дежа-вю. И даже не опечатка. Чуть ранее вы действительно видели раздел с точно таким же названием, но тогда описывался доступ к файлам с помощью .NET-классов I/O, а теперь рассматривается, как выполняются те же действия с использованием функций библиотеки iostream.
Далее для открытия файлов и считывания информации используется класс ifs~rea:n. В данном случае файл открывается не с помощью конструктора при создании потоковой переменной, а непосредственно, путем вызова метода open. He имеет значения, какой способ вы
Для сохранения информации, считываемой из файла, создается буфер. В данном случае
Затем данные считываются из файла, содержащего числовую информацию. Чтобы прочитав вес числа, используется цикл while. Функция eof на каждой итерации цикла проверяет, остаются ли еще данные для считывания. Поскольку символ окончания файла интерпретируется компилятором как число, чтобы он тоже не был отображен на экране как одно из
Обратите внимание также на то, что информация из текстовых файлов считывается по
Вверх
Ниже вы можете увидеть некоторые команды, которые включаются в поток для того, чтобы управлять способом чтения и записи данных. Сами по себе эти команды (называемые потоковыми манипуляторами) никуда не записываются и не считываются. Они лишь определяют особенности считывания или записи следующих за ними элементов:
Можно также использовать приведенный ниже код как вариант преобразования значения
Вверх
По умолчанию числа выводятся на экран, на печать или записываются в файлы без добавления между ними каких-либо символов или пробелов. Если необходимо, их можно разделять
Вместо пробелов могут быть использованы какие-то другие символы. Например, можно
Этот же прием можно использовать и при записи числовых данных в потоковые файлы.
Вверх
Ниже приведено несколько советов, которые помогут вам при работе с файлами данных.
Назад |
Начало урока |
Вверх |
Вперед
Потоки данных
В этой главе:
В этой главе вы узнаете о чтении и записи данных в файлы и из файлов.
Как записывать и считывать данные разных типов.
Как осуществлять контроль формата исходящих данных.
другие. Библиотеки классов среды .NET включают в себя набор потоковых классов,
предназначенных для организации процесса ввода-вывода. (Иногда ввод-вывод обозначается как I/O, что является сокращением от слов input/output.) Если вы пишете неуправляемую программу, к вашим услугам — библиотека функций iostream, которые также обслуживают процесс ввода-вывода данных.
Считывать и сохранять данные можно множеством способов. И библиотека iostream, и
.NET-классы ТО обеспечивают режим, при котором вам не нужно вникать во множество технических деталей, так как все они выполняются автоматически.
.NET-классы I/O
В пространстве имен (namespace) System.IO среды .NET есть некоторое количество классов, предназначенных для организации процесса ввода-вывода информации в файлы и из файлов. В этой главе вы познакомитесь с классом StreamReader, который обеспечивает процесс чтения текста из файла, и с классом StreamWriter, который обеспечивает процесс записи текста в файл. Класс File используется как вспомогательный для создания объектов StreamReader и StreamWriter. Вот как открывается потоковый файл для записи текста:
StreamWriter *poWStream = File::CreateText( S "test.txt" ) ;
poWStream->Write(S"Hello this is a test" ) ;
Метод Write является перегружаемым, благодаря чему вы можете записывать в файл
значения различных типов, например double или integer. Если нужно записать информацию, которая заканчивается символом окончания строки, вызовите метод WriteLine. К тому же не забывайте, что методы Write и WriteLine обладают возможностями форматирования, а потому вы можете набирать коды, наподобие этого:
pcWStream->Write(S"Hello {0}, you are {1} and {2} !", sName,
nAge, sCute);
Close:poWStream->Close();
poRStream = File::OpenText(S"test.txt");
Console::WriteLine(poRStream->ReadLine());
poRStream~>Close();
using namespace System::IO;
Записали — прочитали
из этих же файлов. Текстовые данные записываются в один файл, а числовые — в другой:
//Открытие потока для записи текста
Далее используется объект класса StreamReader для открытия первого файла с последующим вызовом метода ReadLine для считывания текстовых данных:
StreamWriter poWStream = File::CreateText(S"text.txt");
//запись текста в файл
poWStream->WriteLine(S"Hello this is a test");
//Закрытие потока
poWStream->Close();
poWStream = File::CreateText(S"number.txt");
poWStream->WriteLine(15);
poWStream->WriteLine(42);
poWStream~>WriteLine(1);
poWStream->Close() ;
//Открытие первого файла, считывание строк и отображение
//их на экране
StreamReader *poRStream = File::OpenText(S"text.txt");
String* pszWords = poRStream->ReadLine();
Console::WriteLine(pszWords);
poRStream~>Close() ;
//Считывание числовых данных
String* pszLine;
int nTempNum;
poRStream = File::OpenText(S"numbers.txt") ;
//Считывание значений до тех пор, пока не будет достигнут
//конец файла
while ((pszLine = poRStream->ReadLine()) != 0)
{
Console::WriteLine(nTempNum);
poRStream->Close();
и считать их оттуда. Файл для записи открывается таким несложным кодом:
ofstream foo("filename");
//Запись в файл текста "Hello World"
foo << "Hello World"
Использование класса if stream осуществляется аналогичным образом:
if stream foo("filename");
//Выделение области, куда будут считываться текстовые данные
char buffer[100];
//Считывание текстовых данных из файла
foo >> buffer;
int Mylnt;
foo « Mylnt;
библиотеку iostream, для чего в начале программы наберите
#include <fstream.h>
Повторное использование потоковых переменных
вается. Но закрыть этот файл можно и раньше, воспользовавшись функцией-членом close:
//Закрытие файла, представляемого потоковой переменной foo
foo.close();
//Открытие файла "foo.txt"
foo.open("foo.txt");
Записали — прочитали
В этом разделе также рассматривается пример программы, в процессе выполнения которой вначале в файлы записываются текстовые и числовые данные, а затем эти же данные считываются. Текстовые данные записываются в один файл, а числовые — в другой:
//Открытие файла new.txt
ofstream oOutFile("new.txt");
//Запись Б этот файл текстовой информации
oOutFiie << "Row, row, row your boat";
//Теперь этот файл закрывается
oOutFile.close();
//Открытие другого файла и запись в него числовых данных.
//Обратите внимание, что числа отделяются друг от друга
//пробелами
oOutFile.open("number.txt") ;
oOutFile << 15 << " " « 42 << " " << 1;
oOutFile.close();
выберете, оба работают одинаково хорошо.
ifstream oInFile;
оInFile.open
("new. txt." ) ;
размер буфера равен пятидесяти байтам. Убедитесь, что размер используемого вами буфера
больше самого большого элемента, который должен быть считан. Если вы точно знаете, эле-
менты какого размера должны считываться, сделайте буфер больше, чем размер любого из
этих элементов. С другой стороны, установив размер буфера, вы можете ограничить макси-
мальный размер принимаемых программой данных.
Данные из файла считываются в буфер и затем по одному элементу за раз отображаются
на экране:
oInFile >> p;
cout << p << endl;
oInFile >> p;
cout << p << endl;
чисел, считываемых из файла, перед командой отображения данных на экране дополнительно
используется оператор if:
//Считывание данных из файла
while (!оInFile.eof())
//Чтение числа
olnFile » nTempNum;
//Если число не является символом окончания файла, оно
//отображается на экране
if (!oInFile.eof())
cout << nTempNum << endl;
}
oInFile.close();
одному слову за раз. Это очень удобно для последующей обработки считываемых данных.
Специальные команды, погружаемые в потоки данных
Например, если вводимое пользователем число должно быть интерпретировано как зна-
чение типа hex, наберите такой код:
cin » hex >> TempNum;
типа hex к значению типа decimal:
//Чтение числа как значения типа hex
cin >> hex >> TempNum;
//Отображение этого же числа как значения типа decimal
cout << dec « TempNum;
Формат передаваемых данных
между собой дополнительными пробелами. Это особенно удобно, если вы хотите разместить
числа по столбцам. Чтобы отделить числа друг от друга пробелами, используйте функцию-
член width:
//Отображение чисел с интервалом в 20 пробелов
cout.width(20);
заполнить пространство между числами звездочками (*), чтобы никто не смог дописать, скажем, к платежному чеку парочку нулей:
//Заполнение звездочками пространства между отображаемыми числами
cout.fill('*');
Записывать данные в файлы, отображать на экране, а также считывать их оттуда можно
тысячами способов. Есть еще множество используемых для этого дополнительных классов, которые в книге не рассматриваются. Если вы хотите стать мастером ввода-вывода, обратитесь к разделу справочной системы Visual C++. который посвящен функциям ios-tream. Помимо чтения общих разделов о потоках данных и потоковых классах, можете обратить особое
внимание на разделы, посвященные методам форматирования, форматирующим флагам и
манипуляторам.
Кое что о работе с файлами
оттуда. Формально это делать можно, но иногда такие действия (особенно это касается начинающих программистов) могут привести к тому, что возникнет путаница в определении места, с которого данные должны считываться, и места, начиная
с которого данные должны записываться.
iostream, числа записываются как текст без каких-либо пробелов между ними.
Так, если вы хотите, чтобы результатом записи чисел в файл была строка
3,4 5,6 66,28 8,
а не
3,45,666,288,
нужно позаботиться о том, чтобы после каждого записываемого числа был добавлен пробел. Для этого можете использовать, например, такой код:
cout << foo « " ";
чания файла и иногда обозначаемый как eof), который говорит компилятору:
"Эй! На мне файл заканчивается". Как только компилятор видит этот символ, он сразу же определяет, что данных для считывания в этом файле больше нет.
файла или символ перехода на новую строку (\n). Если последняя строка файла
не заканчивается символом перехода на новую строку, сразу же после ее считывания фиксируется факт окончания файла.
iostream, символ окончания файла не распознается при считывании последнего числа. (В этом, например, отличие C++ от языка С, в котором при считывании последнего числа определяется факт окончания файла.) Поэтому, если вы не
обратите внимание на данное обстоятельство, программа прочитает символ окончания файла как еще один элемент и попытается преобразовать его в число.
Содержание