85783
Работа с двоичными файлами в ОС Windows на языке С++
Лабораторная работа
Информатика, кибернетика и программирование
Цель работы: изучение методов работы с двоичными файлами и битовой информацией в ОС Windows на языке С++ При записи информации в двоичный файл символы и числа преобразуются в последовательность из байтов. Для того чтобы записать данные в двоичный файл, необходимо: описать файловую переменную...
Русский
2015-03-30
67.89 KB
3 чел.
Лабораторная работа 2. Работа с двоичными файлами в ОС Windows на языке С++
Цель работы: изучение методов работы с двоичными файлами и битовой информацией в ОС Windows на языке С++
При записи информации в двоичный файл символы и числа преобразуются в последовательность из байтов.
Для того чтобы записать данные в двоичный файл, необходимо:
Для того чтобы считать данные из двоичного файла, необходимо:
Рассмотрим основные функции, необходимые для работы с двоичными файлами.
Для открытия файла в зависимости от используемых библиотек используются функции fopen или fopen_s . В них последним параметром является mode - строка, определяющая режим работы с файлом; возможны следующие ее значения:
Для закрытия файла предназначена функция fclose
int fclose(FILE *filename);
Возвращает 0 при успешном закрытие файла и NULL в противном случае. Функция remove предназначена для удаления файлов.
int remove(const char *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:
int feof(FILE *filename);
Она возвращает ненулевое значение если достигнут конец файла.
Для просмотра содержимого двоичных (бинарных) файлов необходимы специальные программы. Обычно они представляют двоичную байтовую информацию в шестнадцатеричной системе счисления. В ней каждый байт, состоящий из 8 бит, разбивается на две тетрады (части по 4 бита), которые заменяются одной шестнадцатеричной цифрой по правилу:
Для записи целых шестнадцатеричных чисел в отдельные байты в языке С++ используется шестнадцатеричная форма записи, начинающаяся с Ох. Например, после присваиваний:
char s1,s2
s1=OxAB;
s2=Ox2F;
в байтах s1 и s2 будут содержаться шестнадцатеричные числа AB16 и 2F16, которые соответствуют двоичным словам 101010112 и 001011112.
Шестнадцатеричная система счисления позволяет непосредственно записывать двоичные числа в байты. Например, если в байт s1 необходимо записать последовательность значений 8 бит, равную 101011002, то сначала эта последовательность разбивается на две тетрады (10102 и 11002), они переводятся в соответствующие шестнадцатеричные числа (А16 и C16), а затем выполняется присваивание:
s1=OxAC;
Для считывания отдельных байтов (в переменную типа char) с игнорированием пробелов можно использовать создание потока и обычны й потоковый вывод.
Пример 1. Написать функцию prf(string f) для вывода на экран содержимого каждого байта файла с именем 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; fstream pf; pf.open(f);//открываем файл в режиме чтения a=new unsigned char[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"); } Задания: 1. Модифицировать текст программы таким образом, чтобы на экран каждое новое значение выводилось бы в системе счисления с основанием 4. 2. Модифицировать текст программы таким образом, чтобы на экран каждое новое значение выводилось бы в одной строке в системе счисления с основанием 16 через два пробела. Для считывания всех подряд байтов (в том числе - пустых) можно использовать функцию 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; double a; 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"); } Задания: 1. Модифицировать текст программы таким образом, чтобы в файл записывались не вещественные, а целочисленные значения. 2. Модифицировать текст программы таким образом, чтобы в файл после каждого вещественного числа записывалось целочисленное значение, равное вещественному с отброшенной дробной частью. 3. Модифицировать текст программы таким образом, чтобы в заданный двоичный файл записывались 5 вводимых с экрана логических значений (0 false, 1 - true). Пример 4. Вывести на экран содержимое созданного в прошлой задаче двоичного файла D:\\str.dat в виде вещественных чисел. Решение:
|
|||
Двоичный файл последовательная структура данных, после открытия файла доступен первый байт, хранящийся в нем. Можно последовательно записывать или считывать данные из файла.
В случае объемных файлов удобнее использовать функцию fseek перемещения указателя файла к заданному байту.
int fseek(FILE *filename, long int offset, int origin);
Функция устанавливает указатель текущий позиции файла F в соответствии со значением начала отсчета origin и смещения offset. Параметр offset равен количеству байтов, на которые будет смещен указатель файла относительно начала отсчета, заданного параметром origin. В качестве значения для параметра origin должно быть взято одно из следующих значений отсчета смещения offset, определенных в заголовке stdio.h:
Функция возвращает нулевое значение при успешном выполнение операции, ненулевое при возникновении сбоя при выполнении смещения
Функция fseek фактически реализует прямой доступ к любому значению в файле. Необходимо только знать месторасположение (номер байта) значения в файле.
Пример 5. Выдать вещественное число с номером 15 из двоичного файла "D:\\num.dat", содержащего вещественные числа, на экран двумя способами: 1) c помощью последовательного доступа (вариант 1); 2) при помощи указателя fseek (вариант 2)..
Решение.
#include "stdafx.h"
#include <iostream>
using namespace std;
void main() { setlocale (LC_ALL, "RUS");
int n, i;
double a;
FILE *f;
fopen_s(&f,"D:\\num.dat", "rb");
for (i=0; i<14; i++)
fread(&a, sizeof(double), 1, f);
cout<<"Var1 a="<<a<<"\n";
fseek(f,14*sizeof(double),SEEK_SET);
fread(&a,sizeof(double),1,f);
cout<<"Var2 a="<<a<<"\n";
fclose(f);
system("pause");
}
Задания:
1. Модифицировать текст программы для аналогичного считывания из файла, содержащего целые числа типа int.
2. Модифицировать текст программы таким образом, чтобы на экран трижды было выведено последнее число файла, а затем дважды предпоследнее.
Пример 6. В созданном ранее двоичном файле D:\\str.dat поменять местами наибольшее и наименьшее из вещественных чисел.
Решение. Алгоритм решения задачи состоит из следующих этапов:
Текст программы решения задачи с комментариями.
#include "stdafx.h"
#include <iostream>
using namespace std;
int main()
{
setlocale (LC_ALL, "RUS");
int n, i, imax, imin;
double *a, max, min;
FILE *f;
//открытие файла в режиме чтения и записи
fopen_s(&f,"D:\\str.dat", "rb+");
//считываем из файла в переменную n количество
//вещественных чисел в файле
fread(&n, sizeof(int), 1, f);
cout<<"n="<<n<<endl;
a=new double[n]; //выделение памяти для хранения вещ. чисел в массиве a
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); //закрытие файла
cout<<"Максимальный элемент = "<<max<<"\n";
cout<<"Минимальный элемент = "<<min<<"\n";
delete []a; //освобождение памяти
system("pause");
return 0;
}
Задания:
1. Модифицировать текст программы таким образом, чтобы на экран дополнительно выводились номера максимального и минимального значения.
2. Модифицировать текст программы таким образом, чтобы максимальный элемент менялся бы местами с начальным элементом файла, а минимальный с последним.
Байтовые величины, содержащие по 8 бит, имеют тип char. Зачастую требуется определить либо изменить отдельные биты внутри байта. Для этого необходимо использовать двоичную запись целого числа типа int, соответствующего байту.
Переход от символьной кодировки к коду целого числа типа int осуществляется путем изменения их типа. Затем для перехода к двоичному представлению полученное число необходимо разложить по степеням числа 2.
Пример 7. Для байта ch, который находится на 8 месте в файле D:\\fсhar.dat с символьной информацией, найти двоичные разряды в его двоичном представлении, занести их в массив d[8] и выдать на экран. Для поиска байта использовать указатель fseek.
Решение..
#include "stdafx.h"
#include <iostream>
using namespace std;
void main() { setlocale (LC_ALL, "RUS");
int n, i, ost, r;
char a;
FILE *f;
fopen_s(&f,"D:\\num.dat", "rb");
fseek(f,7*sizeof(char),SEEK_SET);
fread(&a,sizeof(char),1,f);
cout<<"char a="<<a<<"\n";
n = (int) a;
cout<<" int n="<<n<<"\n";
int d = new int [8];
for (i=0, i<8; i++) { d[7-i]= (n mod 2); n=n/2; cout<<" d["<<7-i<<"]=”<<d[7-i]<<”\n";};
fclose(f);
system("pause");
}
Пример 8. Логический массив int d[8] содержит логические значения false (0) и true (1). Значения элементов массива инициализируются в программе. Требуется сформировать в файле D:\\fсhar.dat байт ch с номером 5, который в своих разрядах содержит данные логические значения. Например, для массива d[8] = {1,0,1,1,0,0,1,0} должен быть сформирован байт ch с содержимым 101100102. Все предыдущие байты заполнить нулевыми значениями.
Решение..
#include "stdafx.h"
#include <iostream>
using namespace std;
void main() { setlocale (LC_ALL, "RUS");
int n, i, st, b;
int d=new int[8];
d = {1,0,1,0,1,0,1,0};
char ch;
FILE *f;
fopen_s(&f," D:\\fсhar.dat ", "wb");
for (i=0, i<5; i++) {// запись нулевых значений в файл
fwrite(0, 1, 1, f);
}
st=1; b=0;
for (i=0, i<8; i++) {// формирование 5-го байта файла
b+=d[7-i]*st; st*=2;
};
Ch = (char) b;
fwrite(ch, 1, 1, f); // запись 5-го байта в файл
fclose(f);
system("pause");
}
Задания для самостоятельного выполнения.
А также другие работы, которые могут Вас заинтересовать | |||
30988. | Клиническая диагностика | 23.79 KB | |
Наличие или отсутствие шумов или дополнительных тонов Различают два тона: Систолический при сокращении предсердий желудочков захлопыванием двух и трёх створчатых клапанов колебание стенок аорты и лёгочной артерии в момент систолы желудочков. Диастолический захлопывание полулунных клапанов аорты и лёгочной артерии колебаний этих сосудов в момент диастолы. Усиление второго тона может сопровождаться акцентом на аорте и лёгочной артерии возникает при повышении кровяного давления в большом круге кровообращения нефриты у лошадей при... | |||
30989. | ВИРОБНИЧО-ОРГАНІЗАЦІЙНА ТА ЕКОНОМІЧНА СТРУКТУРИЗАЩЯ ПІДПРИЄМСТВА | 562 KB | |
Іншими словами існування підприємства фірми повязується з тими перевагами які воно забезпечує у процесі виготовлення продукції порівняно з виробництвом тієї самої продукції без організації фірми. Сучасне підприємство це складна відкрита виробничогосподарська і соціальна система яка: складається із взаємозалежних частин виробництв цехів дільниць служб тощо діяльність яких впливає на кінцевий результат виробництва; взаємодіє із зовнішнім оточенням з якого в систему надходять необхідні для виробничої діяльності фактори... | |||
30990. | ПАТОЛОГИЧЕСКАЯ ФИЗИОЛОГИЯ (КОНСПЕКТ ЛЕКЦИЙ) | 159.5 KB | |
Приводит к почечной недостаточности. Неблагоприятно холодное течение воспаления при нейротоксикозе при недостаточности фагоцитарных процессов. Гипоэргия и анергия проявляются в виде недостаточности той или иной системы. Это вызывает снижение бронхиальной проходимости вплоть до возникновения дыхательной недостаточности. | |||
30991. | ІНФОРМАТИКА та КОМП’ЮТЕРНА ТЕХНІКА | 6.63 MB | |
Інформаційна технологія – це людино – машинна технологія збору, обробки та передачі інформації. Це технологія, яка базується на обчислювальній техніці, швидко розвивається, охоплюючи усі види сучасної діяльності: виробництво, управління, науку, освіту, проектні розробки, торгівлю, фінансово-банківські операції, медицину, криміналістику, охорону оточуючого середовища, побут та інше. | |||
30992. | Электронная торговля | 881.5 KB | |
Многие крупные компании уже давно прибегают к электронному бизнесу, электронной коммерции при проведении деловых операций. Электронный обмен данными (Electronic Data Interchange, EDI) по частным компьютерным сетям начался в 60-годы XX века. Он представлял собой обмен документами в стандартном виде | |||
30993. | Характеристика кормів, технологія заготівлі та способи їх ефективного використання у годівлі поросят | 191 KB | |
Особливості обміну речовин у поросят на початку постнатального періоду 1.4 Розвиток внутрішніх органів у поросят за різних рівнів годівлі.5 Раціони режим і техніка годівлі поросят 1. | |||
30995. | Расчёты объёмов вентиляции по углекислоте и влажности в свинарнике | 162 KB | |
Комплексы по выращиванию и откорму свиней должны находиться на режиме предприятий закрытого типа. В производственную зону комплекса запрещается вход посторонним лицам и въезд на территорию транспорта, не связанного с обслуживанием комплекса. Обслуживающему персоналу разрешается вход на территорию комплекса только через санпропускник, а въезд транспорта- через дезинфекционно- промывочное помещение (дезбарьер). | |||
30996. | Какие изменения в кормах могут возникнуть вследствие влияния на них неблагоприятной погоды | 85.12 KB | |
Расчетная часть. При выполнении курсовой работы нужно дать ответы на такие вопросы: Определить часовой объем вентиляции. Сравнить приходную и расходную части теплового баланса и определить ∆t теплового баланса. У людей от хлеба со спорыньей бывают судороги общий паралич и часто смерть. | |||