Программа 56. Сравнение текстового и бинарного файлов
В программе создаются два выходных файловых потока: текстовый и бинарный. Потоки связываются с файлами конструктором, которому в качестве аргумента передаются имена файлов. В файлы записываются случайные числа соответственно в текстовом и бинарном виде. Созданные файлы закрываются и открываются вновь как бинарные, для передачи функции FileSize, определяющей их размеры. Чтобы прочитать содержимое файла, хранящего текстовое представление чисел, он сначала закрывается как бинарный, а затем открывается на ввод как текстовый. Файл с бинарным представлением чисел подготавливается к чтению перемещением текущего указателя к началу файла. Содержимое файлов выводится на экран.
// Файл CmpTxtBn.cpp
#include <stdlib>
#include <fstream>
#include <iostream>
#include <windows>
#include <time.h>
#include <conio>
const int lenname = 13; // Длина имени файла
using namespace std; // Открываем стандартное пространство имен
char Buff[500]; // Буфер для преобразованной строки
char* Rus(char* in) // Функция для преобразования русских букв
{
CharToOem(in, Buff); // Функция CharToOem преобразует строку in
return Buff; // в строку Buff, используя кодировку DOS
}
long FileSize(istream& f) // Возвращает размер файла в байтах
{ // f – ссылка на поток
long k; // Счетчик
for (k = 0; !f.eof(); k++) // Пока не достигнут конец файла,
f.get(); // читаем из него символ
f.clear(); // Сброс флагов ошибок потока
return k - 1;
}
В функции FileSize производится посимвольное чтение из файла, пока не будет достигнут его конец. Состояние «конец файла» не возникает после прочтения последнего символа, оно возникает после первой неудачной попытки прочитать из файла символ, поэтому возвращается не общее число k вызовов функции get, а значение k - 1, равное числу прочитанных из файла символов.
void main()
{
char* tf = "TxtFile.txt"; // Имя текстового файла
char* bf = "BinFile.bin"; // Имя бинарного файла
const int N =20; // Количество чисел
ofstream tout(tf, ios::out); // Создаем выходной текстовый поток
if(!tout){ // Проверяем открытие файла
cout<<Rus("\nНе могу создать файл") << tf;
cin.get();
exit(1);
}
ofstream bout(bf, ios::out | ios::binary); // Выходной бинарный поток
if(!bout){ // Проверка
cout<<Rus("\nНе могу создать файл") << bf;
cin.get();
exit(1);
}
int i, n;
randomize(); // Инициализация датчика случайных чисел
for(i = 0; i < N; i++){
n = rand(); // Генерируем числа
tout << ' ' << n; // и заносим в текстовый
bout.write((char*)&n, sizeof(int)); // и бинарный файлы
}
tout.close(); // Закрываем
bout.close(); // потоки
ifstream tin(tf, ios::binary); // Открываем оба файла на чтение
ifstream bin(bf, ios::binary); // как бинарные
cout << Rus("\nРазмер текстового файла ") << tf
<< " = " << FileSize(tin);
cout << Rus("\nРазмер биарного файла ") << bf
<< " = " << FileSize(bin);
tin.close(); // Закрываем файл с текстовым представление чисел,
tin.open(tf); // окрываем снова как текстовый
if(!tin){
cout<<Rus("\nНе могу открыть файл ") << tf;
cin.get();
exit(1);
}
// Вывод чисел из обоих файлов
cout << Rus("\nЧисла из файла ") << tf << endl;
while(tin.good()){ // Пока в потоке нет ошибок,
tin >> n; // читаем число из файла
cout << n << ' '; // и выводим на экран
if(wherex() > 60) // Если использовали более 60 позиций экрана,
cout << endl; // переходим на новую строку
}
bin.seekg(0, ios::beg); // Перемещаем текущий указатель файла
// к его началу
cout << Rus("\nЧисла из файла ") << bf << endl;
while(bin.good()){
bin.read((char*)&n, sizeof(int)); // Читаем байты числа
if(!bin.eof()) // Если после чтения не достигнут конец файла
cout << n << ' '; // выводим число
if(wherex() > 60)
cout << endl;
}
tin.close(); // Закрываем
bin.close(); // потоки
cin.get();
}
Для проверки возможности чтения из потока использована функция
bool good() const;
которая возвращает истину, если из потока возможно чтение. Эта функция более надежна, чем eof.
Функция
int wherex();
возвращает текущую горизонтальную координату курсора. Курсор переводится на новую строку экрана, если текущая координата курсора больше 60.
Для записи в текстовый файл и чтения из него использованы обычные операторы вывода << и ввода >>. Для записи в бинарный файл использована функция write, для чтения – read. Подробнее о них см. §14.8.
Далее приводятся результаты, выводимые программой. В тестовом файле числа хранятся в виде последовательностей десятичных цифр, разделенных пробелами. Если открыть файл TxtFile.txt, то увидим в нем числа в виде одной длинной строки. Если открыть бинарный файл в текстовом редакторе, то увидим непрерывную последовательность непонятных значков.
Размер бинарного файла равен 80 байт, так как в него записано 20 целых чисел, каждое их которых занимает 4 байта. Размер тестового файла оказался больше, так как многие числа пятизначные, кроме того между числами ставятся пробелы.
Размер текстового файла TxtFile.txt = 117
Размер бинарного файла BinFile.bin = 81
Числа из файла TxtFile.txt
5100 5643 23190 21957 16631 26794 23086 2043 29278 17418 25104
17502 3733 13662 20114 25132 14391 11375 31451 27970
Числа из файла BinFile.bin
5100 5643 23190 21957 16631 26794 23086 2043 29278 17418 25104
17502 3733 13662 20114 25132 14391 11375 31451 27970