Программные методы работы с двоичными файлами — КиберПедия 

Историки об Елизавете Петровне: Елизавета попала между двумя встречными культурными течениями, воспитывалась среди новых европейских веяний и преданий...

Таксономические единицы (категории) растений: Каждая система классификации состоит из определённых соподчиненных друг другу...

Программные методы работы с двоичными файлами

2022-02-10 61
Программные методы работы с двоичными файлами 0.00 из 5.00 0 оценок
Заказать работу

2.9.1. Функции для работы с двоичными файлами

 

При записи информации в двоичный файл символы и числа преобразуются в последовательность из байтов.

Для того чтобы записать данные в двоичный файл, необходимо:

  1. описать файловую переменную типа FAIL * с помощью оператора FILE *filename;. Здесь filename — имя переменной, где будет храниться указатель на файл.
  2. открыть файл с помощью функции fopen
  3. записать информацию в файл с помощью функции fwrite
  4. закрыть файл с помощью функции fclose

Для того чтобы считать данные из двоичного файла, необходимо:

  1. описать переменную типа FILE *
  2. открыть файл с помощью функции fopen
  3. считать необходимую информацию из файла с помощью функции fread, при этом следить за тем достигнут ли конец файла.
  4. закрыть файл с помощью функции fclose

Рассмотрим основные функции, необходимые для работы с двоичными файлами.

Для открытия файла в зависимости от используемых библиотек используются функции fopen или fopen_ s. В них последним параметром является mode - строка, определяющая режим работы с файлом; возможны следующие ее значения:

  • «rb» — открываем двоичный файл в режиме чтения;
  • «wb» — создаем двоичный файл для записи; если он существует, то его содержимое очищается;
  • «ab» — создаем или открываем двоичный файл для дозаписи в конец файла;
  • «rb+» — открываем существующий двоичный файл в режиме чтения и записи;
  • «wb+» — открываем двоичный файл в режиме чтения и записи, существующий файл очищается;
  • «ab+» — двоичный файл открывается или создается для исправления существующий информации и добавления новой в конец файла.

Для закрытия файла предназначена функция fclose

intfclose(FILE *filename);

Возвращает 0 при успешном закрытие файла и NULL в противном случае. Функция remove предназначена для удаления файлов.

intremove(constchar *filename);

Эта функция удаляет с диска файл с именем filenаmе. Удаляемый файл должен быть закрыт. Функция возвращает ненулевое значение, если файл не удалось удалить.

Для переименования файлов предназначена функция rename:

int rename(const char *oldfilename, const char *newfilename);

Первый параметр — старое имя файла, второй — новое. Возвращает 0 при удачном завершении программы.

Чтение из двоичного файла осуществляется с помощью функции fread:

fread(void *ptr, size, n, FILE *filename);

Функция fread считывает из файла filename в массив ptr n элементов размера size. Функция возвращает количество считанных элементов. После чтения из файла его указатель смещается на n*size байт.

Запись в двоичный файл осуществляется с помощью функции fwrite:

fwrite(const void *ptr, size, n, FILE *filename);

Функция fwrite записывает в файл filename из массива ptr n элементов размера size. Функция возвращает количество записанных элементов. После записи информации в файл указатель смещается на n*size байт.

Для контроля достижения конца файла есть функция feof:

intfeof(FILE *filename);

Она возвращает ненулевое значение если достигнут конец файла.

При записи информации в двоичный файл символы и числа преобразуются в последовательность из байтов.

Для закрытия файла предназначена функция fclose

intfclose(FILE *filename);

Возвращает 0 при успешном закрытие файла и NULL в противном случае. Функция remove предназначена для удаления файлов.

intremove(constchar *filename);

Эта функция удаляет с диска файл с именем filenаmе. Удаляемый файл должен быть закрыт. Функция возвращает ненулевое значение, если файл не удалось удалить.

Для переименования файлов предназначена функция rename:

int rename(const char *oldfilename, const char *newfilename);

Первый параметр — старое имя файла, второй — новое. Возвращает 0 при удачном завершении программы.

Чтение из двоичного файла осуществляется с помощью функции fread:

fread(void *ptr, size, n, FILE *filename);

Функция fread считывает из файла filename в массив ptr n элементов размера size. Функция возвращает количество считанных элементов. После чтения из файла его указатель смещается на n*size байт.

Запись в двоичный файл осуществляется с помощью функции fwrite:

fwrite(const void *ptr, size, n, FILE *filename);

Функция fwrite записывает в файл filename из массива ptr n элементов размера size. Функция возвращает количество записанных элементов. После записи информации в файл указатель смещается на n*size байт.

Для контроля достижения конца файла есть функция feof:

intfeof(FILE *filename);

Она возвращает ненулевое значение если достигнут конец файла.

2.9.2. Просмотр содержимого двоичных файлов

 

Для просмотра содержимого двоичных (бинарных) файлов необходимы специальные программы. Обычно они представляют двоичную байтовую информацию в шестнадцатеричной системе счисления. В ней каждый байт, состоящий из 8 бит, разбивается на две тетрады (части по 4 бита), которые заменяются одной шестнадцатеричной цифрой по правилу:

1. 00002 - 016;                    8) 10002 - 816;

2. 00012 - 116;                    9) 10012 - 916;

3. 00102 - 216;                10) 10102 - A16;

4. 00112 - 316;                11) 10112 - B16;

5. 01002 - 416;                    12) 11002 - C16;

6. 01012 - 516;                    13) 11012 - D16;

7. 01102 - 616;                    14) 11102 - E16;

8. 01112 - 716;                    15) 11112 - F16.

Для записи целых шестнадцатеричных чисел в отдельные байты в языке С++ используется шестнадцатеричная форма записи, начинающаяся с Ох. Например, после присваиваний:

chars1,s2

s1=OxAB;                

s2=Ox2F;

в байтах s1 и s2 будут содержаться шестнадцатеричные числа AB16 и 2F16, которые соответствуют двоичным словам 101010112 и 001011112.

       Шестнадцатеричная система счисления позволяет непосредственно записывать двоичные числа в байты. Например, если в байт s1 необходимо записать последовательность значений 8 бит, равную 101011002, то сначала эта последовательность разбивается на две тетрады (10102 и 11002), они переводятся в соответствующие шестнадцатеричные числа (А16 и C16), а затем выполняется присваивание:

s1=OxAC;

Для считывания отдельных байтов (в переменную типа char) с игнорированием пробелов можно использовать создание потока и обычны й потоковый вывод.

  Пример 1. Написать функцию prf(stringf) для вывода на экран содержимого каждого байта файла с именем f в виде символа, шестнадцатеричного числа и двоичного числа. Между выводимыми числами поставить знак “=” (равенство).Для примера вывести на экран содержимое бинарного файла C:\\TEXT\\d.dat. Решение: #include "stdafx.h" #include <iostream> #include <fstream> #include <iomanip> #include <stdlib.h> #include <string> using namespace std; void prf(string f);   void main(){ string p; p="C:\\TEXT\\d.dat"; prf(p); }   void prf(string f) { setlocale (LC_ALL, "RUS"); unsigned int n, i,j,b,b2,st,fc,sc; unsigned char G[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; unsigned int *d = new unsigned int [8]; unsigned char *a; char ch, F, S; fstreampf; pf.open(f);//открываем файл в режиме чтения a=newunsignedchar[1000]; //выделение памяти для буферного массива а i=0; while (!pf.eof()){ //запись содержимого файла в буферный массив а pf>>ch; a[i]=(unsigned int)ch; i+=1; //чтение очередного байта из файла в массив a }; n=i-1; for (i=0; i<n; i++) { cout<<a[i]<<"=";//выводсимвола a[i] наэкран b=(int)a[i]; //перевод символа в целочисленное представление fc=b/16; sc=b-fc*16; F = G[fc]; S = G[sc];//перевод символа в 16-ричный вид cout<<F<<S<<"=";//вывод 16-ричной кодировки символа a[i] на экран for (j=0; j<8; j++) { b2=b/2; d[j]= b-2*b2; b=b2; };//перевод символа в двоичный вид cout<<d[7]<<d[6]<<d[5]<<d[4]<<d[3]<<d[2]<<d[1]<<d[0];//вывод 2-чной кодировки символа a[i] на экран cout<<endl; // переход на новую строку }; pf.close(); //закрываемфайл system("pause"); } 2.9.3. Чтение и запись в двоичные файлы        Для считывания всех подряд байтов (в том числе - пустых) можно использовать функцию fscanf_s. Пример 2. Написать функцию prfp(char * name)для вывода на экран содержимого каждого байта файла с заданным именем в виде символа, шестнадцатеричного числа и двоичного числа. Между выводимыми числами поставить знак “=” (равенство).Для примера вывести на экран содержимое бинарного файла C:\\TEXT\\d.dat.   #include "stdafx.h" #include <iostream> #include <fstream> #include <iomanip> #include <stdlib.h> #include <string> using namespace std;   void prfp(char * name);   void main(){ char * fileName = "C:\\TEXT\\d.dat"; prf(fileName); }   void prfp(char * name) { setlocale (LC_ALL, "RUS"); int n, i,j,b,b2,fc,sc; unsigned char G[16] = {'0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F'}; unsigned int *d = new unsigned int [8]; unsigned char a; unsigned char F, S; FILE *f; char c; char *mc; mc = new char[1000]; int err=fopen_s(&f, name, "r"); if(err){return;}; cout<<"FILE = "; i=-1; while(fscanf_s(f,"%c",&c,1)==1) {        i=i+1; printf("%c",c);      mc[i]=c; }; n=i+1; cout<<endl; for (i=0; i<n; i++) { cout<<mc[i]<<"=";//вывод символа a[i] на экран a = (unsigned char)mc[i]; b=(int)a; //перевод символа в целочисленное представление fc=b/16; sc=b-fc*16; //cout<<"fc="<<fc<<"sc="<<sc; F = G[fc]; S = G[sc];//перевод символа в 16-ричный вид cout<<F<<S<<"=";//вывод 16-ричной кодировки символа a[i] на экран for (j=0; j<8; j++) { b2=b/2; d[j]= b-2*b2; b=b2; };//перевод символа в двоичный вид cout<<d[7]<<d[6]<<d[5]<<d[4]<<d[3]<<d[2]<<d[1]<<d[0];//вывод 2-чной кодировки символа a[i] на экран cout<<endl; // переход на новую строку }; fclose(f); system("pause"); } Рассмотрим примеры записи и чтения содержимого двоичных файлов. Пример 3. Создать двоичный файл D:\\str.dat, записать в него вводимое с клавиатуры целое число n, а затем - n вводимых с клавиатуры вещественных чисел. Решение: #include "stdafx.h" #include <iostream> using namespace std; void main() { setlocale (LC_ALL, "RUS"); int n, i; doublea; FILE *f; // описываем файловую переменную fopen_s(&f,"D:\\str.dat", "wb");// создаем двоичный файл в режиме записи cout<<"n="; cin>>n; //вводчисла n fwrite(&n, sizeof(int), 1, f); // запись целого числаn в файл for (i=0; i<n; i++) { // цикл для ввода c клавиатуры в файл n вещественных чисел cout<<"a=";// вывод на экран запроса на ввод очередного веществен.числа cin>>a; // вводочередного вещественного числа с клавиатуры fwrite(&a, sizeof(double), 1, f); // запись вещественного числа в двоичный файл } fclose(f); // закрываемфайл system("pause"); }   Пример 4. Вывести на экран содержимое созданного в прошлой задаче двоичного файлаD:\\ str. datв виде вещественных чисел. Решение:
  #include "stdafx.h" #include <iostream> using namespace std; int main() { setlocale (LC_ALL, "RUS"); int n, i; double *a; FILE *f; // описание файловой переменной fopen_s(&f,"D:\\str.dat", "rb"); //открытие двоичного файла в режиме чтения fread(&n, sizeof(int), 1, f); // чтение из файла 1-го целого числа в переменную n cout<<"n="<<n<<endl; // вывод числа n на экран a=newdouble[n]; // выделение памяти для массива а из n вещественных чисел fread(a, sizeof(double), n, f); // чтение n веществен. чисел из файла в массив a for (i=0; i<n; i++) cout<<a[i]<<"\t";// выводмассиваанаэкран cout<<endl; // переход на новую строку fclose(f); // закрываемфайл system("pause"); return 0; }

Создать двоичный файл D:\\game\\noobs.dat и записать в него целое число n и n вещественных чисел.

Решение:

#include "stdafx.h" #include <iostream> usingnamespacestd; int main() { setlocale(LC_ALL, "RUS"); int n, i; double a; FILE*f;//описываемфайловуюпеременную //создаемдвоичныйфайлврежимезаписи f=fopen("D:\\game\\noobs.dat", "wb"); //вводчисла n cout<<"n=";cin>>n; fwrite(&n, sizeof(int), 1, f); //циклдлявводаnвещественныхчисел for(i=0;i<n;i++) { //вводочередноговещественногочисла cout<<"a="; cin>>a; //записьвешественногочиславдвоичныйфайл fwrite(&a, sizeof(double), 1, f); } //закрываемфайл fclose(f); system("pause"); return0; }

Пример 2. Вывести на экран содержимого созданного в прошлой задаче двоичного файла D:\\game\\noobs.dat

Решение:

#include "stdafx.h" #include <iostream> usingnamespacestd; int main() { setlocale(LC_ALL, "RUS"); int n, i; double*a; FILE*f;//описываем файловую переменную //открываем существующий двоичный файл в режиме чтения f=fopen("D:\\game\\noobs.dat", "rb"); //считываем из файла одно целое число в переменную n fread(&n, sizeof(int), 1, f); //вывод n на экран cout<<"n="<<n<<endl; //выделение памяти для массива из n чисел a=newdouble[n]; //чтение n вещественных чисел из файла в массив a fread(a, sizeof(double), n, f); //выводмассиванаэкран for(i=0;i<n;i++) cout<<a[i]<<"\t"; cout<<endl; fclose(f);//закрываемфайл system("pause"); return0; }

Двоичный файл — последовательная структура данных, после открытия файла доступен первый байт, хранящийся в нем. Можно последовательно записывать или считывать данные из файла.

Пример 3. Требуется считать пятнадцатое число, а затем первое.

Решение. С помощью последовательного доступа это можно сделать следующим способом:

1 2 3 4 5 6 7 8 9 10 int n, i; double a; FILE*f; f=fopen("D:\\game\\noobs.dat", "rb"); for(i=0; i<15; i++) fread(&a, sizeof(double), 1, f); fclose(f); f=fopen("D:\\game\\noobs.dat", "rb"); fread(&a, sizeof(double), 1, f); fclose(f);

Последовательное чтение чисел из файла, а затем повторное открытие файла — не самый удобный способ извлечения информации из него. Гораздо удобнее использовать функцию fseek перемещения указателя файла к заданному байту.

intfseek(FILE *filename, long int offset, int origin);

Функция устанавливает указатель текущий позиции файла F в соответствии со значением начала отсчета origin и смещения offset. Параметр offset равен количеству байтов, на которые будет смещен указатель файла относительно начала отсчета, заданного параметром origin. В качестве значения для параметра origin должно быть взято одно из следующих значений отсчета смещения offset, определенных в заголовке stdio.h:

  • SEEK_SET — с начала файла;
  • SEEK_CUR — с текущей позиции;
  • SEEK_END — с конца файла.

Функция возвращает нулевое значение при успешном выполнение операции, ненулевое — при возникновении сбоя при выполнении смещения

Функция fseek фактически реализует прямой доступ к любому значению в файле. Необходимо только знать месторасположение (номер байта) значения в файле. Пример 4. В созданном ранее двоичном файле D:\\game\\noobs.dat, поменять местами наибольшее и наименьшее из вещественных чисел.

Решение. Алгоритм решения задачи состоит из следующих этапов:

1. чтение вещественных из файла в массив a.

2. поиск в массиве а максимального (max) и минимального (min) значения и их номеров (imax, imin).

3. перемещения указателя файла к максимальному значению и запись min.

4. перемещения указателя файла к минимальному значению и запись max.

Текст программы решения задачи с комментариями.

#include "stdafx.h" #include <iostream> usingnamespacestd; int main() { setlocale(LC_ALL, "RUS"); int n, i, imax, imin; double*a, max, min; FILE*f; //открытие файла в режиме чтения и записи f=fopen("D:\\game\\noobs.dat", "rb+"); //считываемизфайлавпеременнуюколичество //вещественныхчиселвфайле fread(&n, sizeof(int), 1, f); cout<<"n="<<n<<endl; //выделяемпамятьдляхранениявещественны чисел, //которыебудутхранитьсявмассивеa a=newdouble[n]; //считываемизфайлавмассивавещественныечисла fread(a, sizeof(double), n, f); //поискмаксимальногоиминимальногоэлементов //вмассивеаиихиндексов for(imax=imin=0, max=min=a[0], i=1; i<n; i++){ if(a[i]>max){max=a[i];imax=i;} if(a[i]<min){min=a[i];imin=i;}} //перемещениеуказателякмаксимальномуэлементу fseek(f, sizeof(int)+imax*sizeof(double), SEEK_SET); //записьminвместомаксимальногоэлементафайла fwrite(&min, sizeof(double), 1, f); //перемещениеуказателякминимальномуэлементу fseek(f, sizeof(int)+imin*sizeof(double), SEEK_SET); //записьmaxвместоминимальногоэлементафайла fwrite(&max, sizeof(double), 1, f); //закрытиефайла fclose(f); //освобождениепамяти delete[]a; system("pause");return0; }
 

 


Поделиться с друзьями:

Архитектура электронного правительства: Единая архитектура – это методологический подход при создании системы управления государства, который строится...

Автоматическое растормаживание колес: Тормозные устройства колес предназначены для уменьше­ния длины пробега и улучшения маневрирования ВС при...

Эмиссия газов от очистных сооружений канализации: В последние годы внимание мирового сообщества сосредоточено на экологических проблемах...

Организация стока поверхностных вод: Наибольшее количество влаги на земном шаре испаряется с поверхности морей и океанов (88‰)...



© cyberpedia.su 2017-2024 - Не является автором материалов. Исключительное право сохранено за автором текста.
Если вы не хотите, чтобы данный материал был у нас на сайте, перейдите по ссылке: Нарушение авторских прав. Мы поможем в написании вашей работы!

0.01 с.