Запись и чтение данных в двоичном режиме
Запись и чтение данных в текстовых файлах
Запись и чтение данных в текстовых файлах ничем не отличается от способов ввода-вывода данных с помощью потоков cin и cout. Методы форматирования вывода и вводы данных остаются такими же (флаги форматирования, манипуляторы, функции потоков).
Необходимо помнить, что при использовании операции >> для чтения данных из текстовых файлов, процесс чтения останавливается при достижении пробельного символа (так же как и в потоках cin и cout). Поэтому для чтения строки текста, содержащей несколько слов, необходимо, как и раньше, использовать, например, функцию getline ().
Для работы с файлом в двоичном режиме его необходимо открыть с флагом ios:: binary.
Чтение и запись двоичных данных в этом режиме можно осуществлять двумя способами:
· по одному байту – функции файловых потоков get () и put ();
· блокам определенной длины - функции файловых потоков read () и write ().
Один из вариантов прототипов функций get () и put () (чаще всего используемый) выглядит так:
|
|
ifstream & get (char & ch);
ofstream & put (char ch);
Функция get () берет один символ из потока ввода, помещает его в символьный параметр ch и возвращает ссылку на поток ввода. Когда достигается конец файла, значение ссылки на поток становится равным 0.
Функция put () помещает символ ch в поток вывода и возвращает ссылку на поток вывода.
В следующей программе с помощью этих функций осуществляется запись в файл массива А из 5 целых чисел, чтение из файла этих данных в массив В и вывод массива В на экран:
int main ()
{
setlocale (0, "");
// Запись массива А в_файл "E:\test.dat"
ofstream o_File; // Создали поток вывода для записи данных в файл
o_File.open ("E:\\test.dat", ios::binary); // Открыли файл
if (! o_File.is_open()) // Проверили, удалось ли открыть файл
{
cout << "Открыть файл не удалось! \n";
return 0;
}
// Записываем данные из массива А в файл
int A[5] = {1, 2, 3, 4, 5};
char *ch = (char *) A; // ch – ссылка на массив А, как на массив символов (байт)
for (int I = 0; I < sizeof(A); ++ I)
o_File.put(ch[I]);
o_File.close(); // Закрываем файл
// Чтение данных из_файла "E:\test.dat" в массив В;
ifstream i_File; // Создали поток ввода для чтения данных из файла
i_File.open ("E:\\test.dat", ios::binary); // Открыли файл
if (! i_File.is_open()) // Проверили, удалось ли открыть файл
{
cout << "Открыть файл не удалось! \n";
return 0;
}
// Читаем данные из файла в массив B
int B[5];
ch = (char *) B; // ch – ссылка на массив В, как на массив символов (байт)
int I = 0;
i_File.get(ch[I++]);
// Предыдущий цикл можно записать короче, например, так:
// while (i_File.get(*ch++);
i_File.close(); // Закрываем файл
// Выводим массив В на экран
for (I = 0; I < 5; ++ I)
cout << B[I] << " ";
cout << endl;
system("pause");
return 0;
|
|
}
А вот как выглядит та же программа при использовании блочных функций чтения и записи (read () и write ()) в двоичном режиме:
int main ()
{
setlocale (0, "");
// Запись массива А в_файл "E:\test.dat"
ofstream o_File; // Создали поток вывода для записи данных в файл
o_File.open ("E:\\test.dat", ios::binary); // Открыли файл
if (! o_File.is_open()) // Проверили, удалось ли открыть файл
{
cout << "Открыть файл не удалось! \n";
return 0;
}
int A[5] = {1, 2, 3, 4, 5};
o_File.write ((char *) A, sizeof (A)); // Записываем данные из массива А в файл
o_File.close (); // Закрываем файл
// Чтение данных из_файла "E:\test.dat" в массив В;
ifstream i_File; // Создали поток ввода для чтения данных из файла
i_File.open ("E:\\test.dat", ios::binary); // Открыли файл
if (! i_File.is_open()) // Проверили, удалось ли открыть файл
{
cout << "Открыть файл не удалось! \n";
return 0;
}
int B[5];
i_File.read ((char *) B, sizeof (B)); // Читаем данные из файла в массив B
i_File.close (); // Закрываем файл
// Выводим массив В на экран
for (int I = 0; I < 5; ++ I)
cout << B[I] << " ";
cout << endl;
system("pause");
return 0;
}
Функции read () и write () имеют следующие прототипы:
ifstream & read (char * buf, streamsize n);
ofstream & write (const char * buf, streamsize n);
Первый параметр этих функций определяет адрес буфера (некоторого массива символов - байт) для чтения или записи данных в соответствующий файловый поток. Второй параметр задает количество символов – байт, которые необходимо взять из потока или записать в поток (тип данных streamsize – целый тип данных). Размер буфера должен соответствовать значению второго параметра.
Функция write () обеспечивает запись из буфера, адрес которого указан в первом параметре функции, n символов данных в поток вывода и возвращает ссылку на поток.
Функция read () обеспечивает запись из потока ввода n символов данных в память по адресу, указанному в первом параметре buf. При достижении конца файла функция возвращает ссылку на поток, равную 0, а фактическое количество взятых из потока символов может быть меньше, чем значение n второго параметра (буфер заполнен не полностью). Фактическое количество считанных из потока ввода символов после выполнения последней операции чтения можно определить с помощью функции потока ввода gcount(). Следующий пример иллюстрирует использование функций блочного чтения и записи данных из произвольного файла.
void FileToScr (char * FileName)
{
fstream File (FileName, ios::in | ios::binary);
if (!File) // Проверили удалось ли открыть файл
{
cout << "Открыть файл не удалось! \n";
return;
}
char Buf [1024];