Копирование и дозапись двоичных файлов можно выполнить той же функцией f ilecopyO (см. листинг 14.4), открыв потоки как двоичные, например:
// копирование файлов
{ ifstream instrm ("c:/binfiles/oonumberl.bin", std::ios::binary); ofstream outstrm("c:/binfiles/oonumber.new", std::ios::binary); if (instrm) tJilecopy(instrm, outstrm);
}
// дозапись нового файла в конец старого
{ ifstream instrm ("c:/b1nfiles/oonumber2.binH, std::ios::binary); ofstream outstrm("c:/binfiles/oonumber.new",
std::ios::app|std::ios::binary); if (instrm) filecopy(instrm, outstrm);
}
Как и при обработке текстовых файлов, разница заключается только в режиме открытия.
Напишем программу сравнения двоичных файлов, чтобы убедиться, что файл oonumber2.bin совпадает с исходным файлом oonumberl .bin. Реализуем эту операцию в виде функции сравнения filecompare():
bool filecompare(ifstream &first, ifstream &second);
Параметрами этой функции являются открытые потоки (как в функции file-сору ()), а результат — булево значение, равное:
• true, если файлы идентичны;
• false, если файлы различаются.
Нам достаточно сравнить файлы побайтно, выдав значение false при первом различии:
// функция сравнения файлов побайтно bool filecompare(ifstream &first, ifstream &second) { char chl = 0, ch2; while (chl != EOF)
{ chl = first.get(); ch2 = second.get(); if (chl!=ch2) return false;
}
return true;
}
// в главной программе...
ifstream first ("c:/binfiles/oonumberl.bin", std::ios::binary);
ifstream second("c:/binfiles/oonumber2.bin", std::ios::binary);
if(filecompare(first, second)) cout << "Files are equals!"<< endl;
else cout << "Files are not equals!" << endl;
Если файлы совпадают, программа выводит на экран строку Files are equals!
Между прочим, эта же функция сравнения прекрасно работает с любыми текстовыми файлами, поскольку ввод информации Осуществляется посимвольно.
Ввод-вывод объектов в двоичный файл
До сих пор мы выводили в двоичные файлы объекты только встроенных типов. Теперь настала пора разобраться с проблемами, возникающими в двоичных файлах при вводе-выводе объектов произвольного типа. Как мы уже знаем (см. главу 1), размеры классов и структур в памяти зависят от выравнивания. Рассмотрим тот же вопрос с точки зрения записи в двоичный файл. Напишем простую программу (листинг 14.8), в которой просто выведем в двоичный файл несколько структур в двух режимах: с выравниванием по байту и без.
Листинг 14.8. Размеры объектов на диске
#include <fstream> #include <iostream> using namespace std; //#pragma pack(l) int main()
{
ofstream f; class Empty {}; Empty t;
f.open("c:/binfiles/binempty.bin", if(!f.is_open()) abort(); f.write((char *)&t, sizeof(t)); f .closeO ; struct BinNotPackl { double a; char ch; int b; }; BinNotPackl A = { 1.0, 'a', 1}; cout << sizeof(A) << endl; f.open("с:/binfiles/binA.bin if(!f.is_open()) abort(); f.write((char *)&A, sizeof(A)); f .closeO: struct BinNotPack2 { int b; double a; char ch; }; BinNotPack2 В = { 1, 1.0,'a'}: cout << sizeof(B) << endl; f.open("c:/binfiles/binB.bin", ios: if(!f.is_open()) abort(); f.write((char *)&B, sizeof(B)); f .closeO ; return 0;
// выранивание по байту
// пустой класс ios::binary);
// пишем пустой класс
// неупакованная структура
// размер = 24 :binary);
// пишем структуру В
}
Эта простая программа записывает в наш каталог BinFiles три файла: binempty.bin, binA.bin и binB.bin. В первый файл записывается «пустой» класс, а во второй и третий — специально невыровненные структуры. Как выясняется, на диск записывается точно столько же байтов, сколько структура занимает в памяти. В системе Visual C++.NET 2003 при отсутствии директивы выравнивания размеры переменных Empty t, BinNotPackl А и BinNotPack2 В равны 1,16 и 24 байт соответственно. Ровно столько же места они занимают и на диске — каждая в своем файле. Если же задать директиву выравнивания, то размеры структур станут равными 13:
#pragma pack(l)
Столько же записывается и в файлы.
В системе Borland С++ Builder 6 наблюдается аналогичная картина. При отсутствии выравнивания на диск записывается 8, 16 и 24 байта . При наличии директивы выравнивания на диск записывается столько же байтов, сколько и в системе Visual С++ - 1, 13 и 13. |