Тарифы Услуги Сим-карты

Записи. Бинарные файлы

Рассматриваемые нами до этого времени примеры демонстрировали форматированный ввод/вывод информации в файлы. Форматированный файловый ввод/вывод чисел целесообразно использовать только при их небольшой величине и малом количестве, а также при необходимости обеспечения возможности просмотра файлов не программными средствами. В противном случае, конечно, гораздо эффективнее использовать двоичный ввод/вывод, при котором числа хранятся таким же образом, как в ОП компьютера, а не в виде символьных строк. Напомню, что целочисленное (int) или вещественное (float) значение занимает в памяти 4 байта, значение типа double – 8 байт, а символьное значение типа char - 1 байт. Например, число 12345 в текстовом (форматированном) файле занимает 5 байт, а в бинарном файле – 4 байта.

Бинарные файлы , т.е. файлы, в которых информация хранится во внутренней форме представления, применяются для последующего использования программными средствами, их невозможно просматривать не программными средствами. Преимущество бинарных файлов состоит в том, что, во-первых, при чтении/записи не тратится время на преобразование данных из символьной формы представления во внутреннюю и обратно, а во-вторых, при этом не происходит потери точности вещественных чисел. Как в случае форматированного ввода/вывода, так и в случае бинарного ввода/вывода для "правильной" обработки информации из файла необходимо знать какие типы данных, каким образом и в какой последовательности записаны в бинарный файл, тем более, что просмотр бинарного файла с помощью текстового редактора ничего не даст.

Рассмотрим пример, демонстрирующий запись целочисленных элементов динамического массива в бинарный файл и чтение их из данного файла.

#include

#include

#include

using namespace std;

cout << "Vvedite kol-vo elementov celochisl. massiva: "; cin >> N;

int *mas = new int [N];

for(i=0; i

cout << " Vvedite " << i << "-i element: "; cin >> mas[i];

cout << "\nIdet zapis dannyh v fail..." << endl;

ofstream fout("c:\\os\\bin.dat", ios::binary); //созд. вых. бинарного потока

if(!fout) { cout << "\n Oshibka otkrytiya faila!"; getch(); return 1; }

fout.write(reinterpret_cast(mas), N*sizeof(int)); //запись массива в файл

fout.close(); //закрытие потока

cout << "Dannye uspeshno zapisany!" << endl;

for(i=0; i

ifstream fin("c:\\os\\bin.dat", ios::binary); //создание потока для чтения файла

if(!fin) { cout << "\n Oshibka otkrytiya faila!"; getch(); return 1; }

cout << "Fail sodergit:" << endl;

fin.read(reinterpret_cast(mas), N*sizeof(int)); //считывание массива из файла

for(i=0; i

getch(); return 0;

Особое внимание в данной программе надо уделить использованию функций write() (метод класса ofstream) и read() (метод класса ifstream). Эти функции думают о данных в терминах байтов и предназначены для переноса определённого количества байт из буфера данных в файл и обратно. Параметрами этих функций являются адрес буфера и его длина в байтах.

Функция write() предназначена для записи в файл указанного во втором параметре числа байт из указанного в первом параметре адреса буфера данных, а функция read() предназначена для считывания данных из файла. Здесь необходимо отметить, что эти функции работают с буфером данных только типа char. В связи с этим, в данной программе мы использовали оператор reinterpret_cast<> , который преобразует буфер наших данных типа int (mas) в буфер типа char.

Необходимо помнить, что приведение типа с помощью оператора reinterpret_cast необходимо только в тех случаях, когда первый параметр функций write() и read() не является символьным массивом (ведь символ типа char занимает только 1 байт). Кроме того, если необходимо записать или прочитать не массив, а отдельные переменные, то нужно использовать ссылочный механизм (ссылку на адрес буфера данных), например:

ofstream fout(filename, ios::app | ios::binary);

fout.write(reinterpret_cast(& cb), sizeof(float));

Теперь необходимо обсудить второй параметр рассматриваемых функций. В данной программе, в качестве второго параметра мы использовали выражение N*sizeof(int), с помощью которого вычислили количество байт. Например, если у нас 5 целочисленных элементов массива, то число байт будет равно 20. Функция sizeof() возвращает количество байт, отводимое под указанный в качестве параметра тип данных. Например, sizeof(int ) вернёт 4.

Итак, приведённая в этом примере программа позволяет записать в файл bin.dat данные в бинарном виде и считывать их из этого бинарного файла. Причём после считывания эти данные приводятся к типу int, приобретают структуру массива и с ними можно производить любые операции.

Теперь, представим себе, что необходимо написать программу позволяющую считывать данные из файла bin.dat, причём мы знаем только то, что в данном файле записаны элементы целочисленного массива в бинарном виде. Количество записанных элементов (N) нам не известно . При создании программы мы не имеем права использовать константный массив, т.е. выделять память под него на этапе создания программы. Это приведет к ошибочному результату. Поскольку слишком малое значение N приведёт к тому, что считаются не все элементы массива, а слишком большое значение N приведёт к заполнению лишних ячеек случайными значениями.

Рассмотрим, пример программы, позволяющей считывать из бинарного файла элементы целочисленного массива, путём динамического выделения памяти, и для доказательства реалистичности считынных данных вычислять их сумму.

#include

#include

#include

using namespace std;

int N, i, sum=0, dfb; //dfb - длина файла в байтах

ifstream fin("c:\\os\\bin.dat", ios::binary );

if(!fin) { cout << "Oshibka otkrytiya faila!"; getch(); return 1; }

fin.seekg(0, ios::end); //устанавливаем позицию чтения на конец файла (от конца 0 байт)

dfb = fin.tellg(); //получаем значение позиции конца файла (в байтах)

N=dfb/4; //зная, что целое число занимает 4 байта, вычисляем кол-во чисел

int *arr = new int [N]; //создаём динамический массив

fin.seekg(0, ios::beg); //перед чтением данных, перемещаем текущую позицию на начало файла

fin.read(reinterpret_cast(arr), dfb);

cout << "Iz faila schitano " << N << " elementov:" << endl;

for(i=0; i

for(i=0; i

cout << "\n Ih summa = " << sum;

getch(); return 0;

Рассмотрим детально данную программу, в которой мы активно использовали функции seekg() и tellg(), являющиеся методами класса ifstream. Здесь необходимо отметить, что с любым файлом при его открытии связывается так называемая текущая позиция чтения или записи . Когда файл открывается для чтения, эта позиция по умолчанию устанавливается на начало файла. Но достаточно часто бывает нужно контролировать позицию вручную, чтобы иметь возможность читать и писать, начиная с произвольного места файла. Функции seekg() и tellg() позволяют устанавливать и проверять текущий указатель чтения, а функции seekp() и tellp() – выполнять те же действия для указателя записи.

Метод seekg(1_параметр, 2_параметр) перемещает текущую позицию чтения из файла на указанное в 1_параметре число байт относительно указанного во 2_параметре места. 2_параметр может принимать одно из трёх значений:

ios::beg – от начала файла;

ios::cur – от текущей позиции;

ios::end – от конца файла.

Здесь beg, cur и end – являются константами, определёнными в классе ios, а символы:: означают операцию доступа к этому классу. Например, оператор fin.seekg(-10, ios::end); позволяет установить текущую позицию чтения из файла за 10 байтов до конца файла.

Теперь вернёмся к описанию работы программы. Исходя из того, что нам не известно количество чисел записанных в файл, вначале необходимо узнать число чисел. Для этого, с помощью fin.seekg(0, ios::end); мы перемещаемся в конец файла и посредством функции tellg() возвращаем в переменную dfb длину файла в байтах. Функция tellg() возвращает текущую позицию указателя в байтах. Так как длина одного целого числа в байтах нам известна (4 байта), нетрудно вычислить количество записанных в файл чисел, зная длину файла в байтах (N=dfb/4; ). Узнав количество чисел, создаём динамический массив и перемещаемся в начало файла для того, чтобы начать считывание данных с помощью функции read(). После того, как указанное нами число байт данных (dfb) перенесено в буфер данных (arr), считанные таким образом данные приобретают структуру массива и становятся полностью пригодны для каких укодно операций и преобразований.

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

Вам понадобится

  • - программа Hex Edit.

Инструкция

  • Загрузите на винчестер прогамму Hex Edit - редактор файлов, представляющий их содержимое в двоичном виде. Откройте программу, дважды кликнув мышью по стартовому файлу. Данное программное обеспечение позволяет в режиме реального времени читать бинарные файлы, изменять содержимое, добавлять свои собственные записи и многое другое. Чтобы полноценно работать в данной среде, вам нужно немного знать об общих понятиях бинарных файлов.
  • Окно программы мало чем отличается от обычного редактора: знакомые меню и панель с кнопками, тело редактируемого файла, закладки и строка состояния. Откройте бинарный файл через меню File или кликнув по соответствующей пиктограмме на панели. Бинарный файл предстанет перед вами в виде строк с цифрами и буквами. Не путайте эти символы с печатными данными текстовых файлов. Их можно также править, удаляя символы, однако при этом вы удалите ячейки с данными, кусочки файла.
  • Внесите изменения в содержимое файла. Приложение может показать важные части файла для более удобного поиска, а также имеет гибкую настройку графического отображения двоичного кода. Переключите вид содержимого в режим ASCII+IBM/OEM, чтобы увидеть программный код файла. Если вы внесете неправильные строки в файл, он может работать некорректно, вызвав при этом серьезные последствия у операционной системы персонального компьютера.
  • Сохраните изменения. Если у вас нет опыта в таком редактировании файлов, будьте готовы к тому, что файл не откроется и откажется работать после внесения изменений. Вы, скорее всего, испортите несколько копий, прежде чем добьетесь результата. Старайтесь не сохранять все изменения в исходный файл, чтобы его содержимое оставалось неизменным.
  • В приведенном выше примере самым "длинным" является вариант "b ": для него требуется 23 байта (21 байт для строки и 2 байта для целого числа). Для вариантов "n " и "m " требуется 4 и 5 байт соответственно (см. таблицу).

    name, publisher item Вариантная часть

    Бинарные файлы

    Бинарные файлы хранят информацию в том виде, в каком она представлена в памяти компьютера, и потому неудобны для человека. Заглянув в такой файл, невозможно понять, что в нем записано; его нельзя создавать или исправлять вручную - в каком-нибудь текстовом редакторе - и т.п. Однако все эти неудобства компенсируются скоростью работы с данными.

    Кроме того, текстовые файлы относятся к структурам последовательного доступа, а бинарные - прямого. Это означает, что в любой момент времени можно обратиться к любому, а не только к текущему элементубинарного файла .

    Типизированные файлы

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

    age: set of 0..18; {в файле задано границами}

    то придется написать следующий код:

    c: char; i,j,min,max: integer;

    a: array of toy;

    begin assign(f,input); reset(f);

    for i:=1 to 100 do if not eof(f)

    then with a[i] do

    begin readln(f,name,price,min,max); age:=;

    for j:= min to max do age:=age+[j];

    Как видим, такое поэлементное считывание весьма неудобно и трудоемко.

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

    непременным условием для организации прямого доступа к элементам бинарного файла : как и в случае массивов, если точно известна длина каждого компонента структуры, то адрес любого компонента может быть вычислен по очень простой формуле:

    <начало_структуры> + <номер_компонента>*<длина_компонента>

    Описание типизированных файлов

    В разделе var файловые переменные, предназначенные для работы стипизированными файлами , описываются следующим образом:

    var <файловая_перем>: file of <тип_элементов_файла>;

    Никакая файловая переменная не может быть задана константой.

    Назначение типизированного файла

    С этого момента и до конца раздела под словом "файл" мы будем подразумевать "бинарный типизированный файл " (разумеется, если специально не оговорено иное).

    Команда assign(f,"<имя_файла>"); служит для установления связи между файловой переменнойf и именем того файла, за работу с которым эта переменная будет отвечать.

    Строка "<имя_файла> " может содержать полный путь к файлу. Если путь не указан, файл считается расположенным в той же директории, что и исполняемый модуль программы.

    Открытие и закрытие типизированного файла

    В зависимости от того, какие действия ваша программа собирается производить с открываемым файлом, возможно двоякое его открытие:

    reset(f); - открытие файла для считывания из него информации и одновременно длязаписи в него (если такого файла не существует, попытка открытия вызовет ошибку). Эта же команда служит для возвращения указателя на начало файла;

    rewrite(f); - открытие файла длязаписи в него информации; если такого файла не существует, он будет создан; если файл с таким именем уже есть, вся содержавшаяся в нем ранее информация исчезнет.

    Закрываются типизированные файлы процедуройclose(f) , общей для всех типов файлов.

    Считывание из типизированного файла

    Чтение из файла, открытого для считывания, производится с помощью команды read() . В скобках сначала указывается имя файловой переменной, а затем - список ввода1) :

    Вводить из файла можно только переменные соответствующего объявлению типа, но этот тип данных может быть и структурированным. Cкажем, если вернуться к примеру, приведенному в начале п. "Типизированные файлы ", то станет очевидным, что использованиетипизированного файла вместо текстового позволит значительно сократить текст программы:

    type toy = record name: string; price: real;

    age: set of 0..18; {задано границами}

    var f: file of toy;

    a: array of toy; begin

    assign(f,input);

    for i:=1 to 100 do

    if not eof(f) then read(f,a[i]); close(f);

    Поиск в типизированном файле

    Уже знакомая нам функция eof(f:file):boolean сообщает о достигнутом конце файла. Все остальные функции "поиска конца" (eoln() ,seekeof() иseekeoln() ), свойственные текстовым файлам, нельзя применять к файламтипизированным .

    Зато существуют специальные подпрограммы, которые позволяют работать с типизированными файлами как со структурами прямого доступа:

    1. Функция filepos(f:file):longint сообщит текущее положение указателя в файлеf . Если он указывает на самый конец файла, содержащегоN элементов, то эта функция выдаст результатN . Это легко объяснимо: элементы файла нумеруются начиная с нуля, поэтому последний элемент имеет номер N-1 . А номерN принадлежит, таким образом, "несуществующему" элементу - признаку конца файла.

    2. Функция filesize(f:file):longint вычислит длину файлаf .

    3. Процедура seek(f:file,n:longint) передвинет указатель в файлеf на началозаписи с номеромN . Если окажется, чтоn больше фактической длины файла, то указатель будет передвинут и за реальный конец файла.

    4. Процедура truncate(f:file) обрежет "хвост" файлаf : все элементы начиная с текущего и до конца файла будут из него удалены. На самом же деле произойдет лишь переписывание признака "конец файла" в то место, куда указывал указатель, а физически "отрезанные" значения останутся на прежних местах - просто они станут "бесхозными".

    Запись в типизированный файл

    Сохранять переменные в файл, открытый для записи , можно при помощи командыwrite() . Так же как и в случае считывания, первой указывается файловая переменная, а за ней - список вывода:

    write(f,a,b,c); - записать в файлf (предварительно открытый длязаписи командамиrewrite(f) илиreset(f) ) переменныеa ,b ,c .

    Выводить в типизированный файл можно только переменные соответствующего описанию типа данных. Неименованные и нетипизированные константы нельзя выводить в

    типизированный файл.

    Типизированные файлы рассматриваются как структуры одновременно и прямого, и последовательного доступа. Это означает, чтозапись возможна не только в самый конец файла, но и в любой другой его элемент. Записываемое значение заместит предыдущее значение в этом элементе (старое значение будет "затерто").

    Например, если нужно заместить пятый элемент файла значением, хранящимся в переменной а , то следует написать следующий отрывок программы:

    seek(f,5); {указатель будет установлен на начало 5-го элемента}

    write(f,a); {указатель будет установлен на начало 6-го элемента}

    Работа с двоичными файлами

    Вся информация хранится в компьютере в виде 0 и 1, т. е. в двоичном виде. Двоичные файлы отличаются от текстовых только методами работы с ними. Например, если мы записываем в текстовый файл цифру «4», то она записывается как символ, и для ее хранения нужен один байт. Соответственно и размер файла будет равен одному байту. Текстовый файл, содержащий запись: «145687», будет иметь размер шесть байт.

    Если же записать целое число 145 687 в двоичный файл, то он будет иметь размер четыре байта, так как именно столько необходимо для хранения данных типа int. То есть двоичные файлы более компактны и в некоторых случаях более удобны для обработки.

    Запись стандартных типов данных в двоичные файлы

    Для того чтобы открыть двоичный файл, необходимо задать режим доступа ios::binary (в некоторых компиляторах C++ - ios::bin).

    Для создания выходного файла создают объект:

    ofstream outBinFile("out.bin", ios::out | ios::binary);

    /* создание объекта класса ofstream out. bin

    if (! out_f і 1) //стандартная проверка

    Запись данных происходит с помощью метода write (), который имеет два параметра: первый - указатель на начало (адрес начала) записываемых данных, второй - количество записываемых байтов. При этом указатель необходимо явно преобразовать к типу char.

    Пример 1. Записать в двоичный файл переменные различного типа:

    ofstream outBinFile("test.bin", ios::out I

    ios: :binary) ; /^создание объекта класса of stream и попытка связать его с файлом test. bin в режиме записи двоичного файла */

    int а - 145687; //объявление целой переменной а

    outBinFi le. write ((char*) &а, sizeof (а)) ; /^запись в файл

    переменной а как потока байтов, т. е. запись в файл внутреннего представления целой переменной а */ float х - 123.25; // объявление вещественной переменной х

    outBinFile .write ((char*) &х, sizeof (х)) ; /^запись в файл

    переменной х как потока байтов, т. е. запись в файл внутреннего представления целой переменной х*/

    //определение символьной переменной с и инициализация ее символом g outBinFile.write((char*)&c, sizeof(c));

    //запись символа g в файл

    outBinFile.close(); return 0;

    Если открыть содержимое файла test .bin текстовым редактором, то он будет иметь вид:

    а размер файла составит 9 байт.

    Чтение стандартных типов данных из двоичных файлов

    Для того чтобы открыть существующий двоичный файл для чтения, нужно создать объект:

    ifstream inpBinFile("inp.bin", ios::in I ios::binary);

    /* используем дизъюнкцию флагов, указывающую на то что файл открывается на чтение в двоичном виде*/

    if (! inpBinFile)

    coutДля чтения данных используем функцию read(), имеющую аналогичные функции write() параметры.

    #include using namespace std; int main()

    ifstream inpBinFile("test.bin", ios::in I

    ios: : binary) ; //открываем файл на чтение в двоичном виде

    int а; float х; char с = "g";

    inpBinFile.read((char*)&a, sizeof(a));

    //читаем целочисленную переменную inpBinFile.read((char*)&x, sizeof(x));

    //читаем вещественную переменную inpBinFile.read((char*)&c, sizeof (c));

    //читаем символьную переменную

    inpBinFile.close(); cout

    Результат работы программы:

    а = 145687 х = 123.25 с = g

    Обратите внимание, что при использовании функции write и read не происходит никакого преобразования информации. В файл записывается и считывается внутреннее представление данных. Именно поэтому две предыдущие программы дали правильный результат.

    Запись и чтение пользовательских типов данных в двоичные файлы

    В отличие от текстовых файлов, работа с пользовательскими типами данных с использованием двоичных файлов ничем не отличается от стандартных типов данных. Аналогично используются методы write() и read(). Программисту только остается указать адрес записываемого участка памяти и количество записываемых байтов, учтя при этом, что никакого преобразования данных не происходит, записывается и считывается только внутреннее представление информации.

    Также при работе с двоичными файлами могут использоваться методы seekg(), tellg(), seekp(), tellp().

    Пример 3. Написать программу, которая записывает сведения о группе туристов в двоичный файл.

    fstream BinFile("ankety.bin", ios::in I ios::out | ios::binary);

    Anketa Gruppa = ; for (int i = 0; i

    BinFile.write((char*)&Gruppa[i], sizeof(Anketa)); BinFile.close(); return 0;

    Пример 4. В файле «ankety.bin» содержатся данные о группе туристов, необходимо считать их и вывести на экран.

    #include using namespace std; struct Anketa {

    char name; int age;

    структурного типа данных Anketa на экран*/

    ostream& operator

    fstream BinFile("ankety.bin", ios::in | ios::out | ios::binary); if (!BinFile)

    for (int i = 0; i

    //сразу читаем все байты, занимаемые переменной типа Anketa BinFile.read((char*)&Gruppa[i], sizeof(Anketa));

    BinFile.close(); return 0;

    Результат работы программы:

    Ivanov, 23 Sidorov, 21 Petrov,22

    Для продолжения нажмите любую клавишу. . .

    Разработка собственных классов для работы с файлами

    Постоянно пользоваться методами write() и read() неудобно, гораздо приятнее иметь возможность пользоваться операциями «>» по аналогии с текстовыми файлами. Приведем пример реализации своего класса для работы с двоичными файлами.

    using namespace std;

    struct Anketa //объявляем структуру для хранения информации

    /*перегрузка операции вставки в поток для вывода пользовательского

    структурного типа данных Anketa на экран*/

    ostream& operator

    class outBinaryFile: public of stream /^определяем свой класс для работы с выходными бинарными файлами. Порождаем его от класса работы с выходными файловыми потоками*/

    /*при описании конструктора порожденного класса не забываем вызвать конструктор базового, передав ему необходимые параметры*/

    outBinaryFile(char* name) : ofstream(name, ios::out I ios::binary)

    //перегружаем необходимые операции как методы класса outBinaryFile& operator

    write((char*)&chislo, sizeof(chislo)); return *this;

    outBinaryFile& operator

    write((char*)&ank, sizeof(ank)); return *this;

    class inpBinaryFile: public if stream /* определяем свои класс для работы с входными бинарными файлами. Порождаем его от класса работы с входными файловыми потоками*/

    inpBinaryFile(char* name) : ifstream(name, ios::in I ios::binary)

    /*вызова конструктора базового класса с необходимыми параметрами,

    достаточно для конструктора порожденного класса */

    //перегружаем необходимые операции

    inpBinaryFile& operator >> (int& chislo)

    read((char*)&chislo, sizeof(chislo)); return *this;

    inpBinaryFile& operator >> (Anketa& ank)

    read((char*)&ank, sizeof(ank)); return *this;

    int а = 111, b = 112; outBinaryFile outFile("dannye.bin");

    //открываем файл на чтение

    inpBinaryFile inpFile("dannye.bin"); if (!inpFile)

    for (int і = 0; i

    inpFile >> a; //читаем анкету из файла

    cout //и выводим ее на экран

    inpFile >> anketa; cout

    Результат работы программы:

    Kolya, 1990, 582-78-95.

    Для продолжения нажмите любую клавишу. . .

    1. Можно ли в программе использовать операцию?

    ios::in I ios::out

    • а) да, в любом случае;
    • б) да, но только при работе с текстовыми файлами;
    • в) нет, в любом случае.
    • 2. Укажите правильный вариант открытия текстового файла для чтения:
      • а) ifstream inpF("input.txt", ios::in);
      • б) ifstream inpF("input.txt", ios::input);
      • в) ifstream inpF(ios:in, "input.txt").

    З.Что будет выведено на экран в результате выполнения следующего кода?

    inputFile.get(с);

    next - inputFile.peek();

    if (next == EOF)

    • а) содержимое файла, связанного с потоком inputFile, выведется на экран один раз;
    • б) содержимое файла, связанного с потоком inputFile, будет выводиться на экран бесконечное число раз;
    • в) на экран ничего не будет выведено.
    • 4. Сколько символов содержится в файле?
    • 12 3 4 5 6
    • а) 6;
    • б) 7;
    • в) 11.
    • 5. Какие методы позволяют определить конец файла?
    • а) eof();
    • б) good();
    • в) оба указанных метода.
    • 6. Для чего предназначена функция getline()?
    • а) считывает слово из файла;
    • б) считывает все содержимое файла;
    • в) считывает строку из файла.
    • 7. Чтобы записывать/считывать пользовательские типы данных в файл, необходимо:
      • а) перегрузить операции «>>» и «
      • б) запись и чтение пользовательских типов данных доступны без дополнительных действий;
      • в) запись и чтение пользовательских типов данных в файл невозможны.
    • 8. Какие функции используются для записи/чтения информации в двоичном виде?
    • а) printf / scanf;
    • б) write / read;
    • в) put / get.
    • 1. Написать программу, которая записывает в файл буквы английского алфавита.
    • 2. В файле input.txt записана информация из нескольких текстовых строк. Вывести содержимое этого файла на экран, посчитать количество строк в файле.
    • 3. На диске находится файл result.txt с результатами химических экспериментов. Написать программу, создающую копию этого файла с именем copy_resylt.txt.
    • 4. С клавиатуры ввести имя файла. В указанном файле удалить все четные строки.
    • 5. Написать программу, которая в текстовом файле, заменяет все строчные буквы прописными, и наоборот.
    • 6. В исходном текстовом файле находятся числа, разделенные пробелами. Сформировать два новых файла: первый должен содержать только четные числа, а второй - нечетные.
    • 7. В файл записаны вещественные числа. Написать программу, которая отбрасывает дробную часть у этих чисел и записывает их в новый файл.
    • 8. В текстовом файле записана информация о рейсах авиакомпании. Выбрать из этих данных рейсы, вылетающие после обеда, и вывести их на экран.
    • 9. Перегрузить операторы >> и
    • 10. Написать собственный класс для работы с бинарными файлами.
    • 11. Записать список 10 учеников класса в текстовый файл и в двоичный файл. Сравнить эти файлы. Объяснить полученное отличие.
    • 12. Разработать класс, который записывает в файл информацию об автомобилях (год выпуска, марку, цвет и т. д.) в текстовый файл. При этом каждый символ информации заменяется своим АБО 1-кодом. Полученный файл вывести на экран.

    Контрольные вопросы

    • 1. Какие классы используются для работы с файловыми потоками?
    • 2. Какие режимы доступа могут использоваться при работе с файлами? Приведите примеры.
    • 3. Какой метод служит для открытия файла? Приведите примеры.
    • 4. Какие операции доступны для работы с файлами? Какие функции предназначены для выполнения этих операций?
    • 5. Какие методы позволяют определить конец файла при чтении из него информации? В чем отличие этих методов? Приведите примеры.
    • 6. Каким образом можно считать переменные стандартных типов данных из текстовых файлов?
    • 7. Можно ли считывать из текстовых файлов переменные пользовательских типов данных?
    • 8. Какие функции предназначены для произвольного чтения информации из файла? Приведите примеры.
    • 9. Назовите особенности двоичных файлов. В чем преимущества использования таких файлов?
    • 10. С помощью каких функций можно записывать/считывать информацию в двоичные файлы?
    • 11. Как считать переменные стандартных типов данных из двоичного файла?
    • 12. Какие особенности нужно учитывать при чтении пользовательских типов данных из двоичных файлов?
    • "Ivanov", 23}, {"Sidorov", 21},

    Сегодня мы поговорим о самой распространённой ошибке, возникающей во время запуска программы SuperSu. Сама проблема проявляется в виде уведомления следующего содержания: «Нет бинарного файла SU и SuperSu». Как обновить бинарный su файл на Андроид? Об этом вы и узнаете из нашего материала.

    SuperSU – специальное приложение для администрирования, позволяющее осуществлять расширенное управление всеми установленными приложениями. Иными словами, с SuperSU вы получаете полный контроль над своим Android-устройством. Подробнее о программе:

    Итак, при запуске SuperSU на экране появилось вот такое сообщение:

    Здесь нужно пояснить, что файл Su является основополагающим компонентом прав «Суперпользователя», поэтому с его удалением вы теряете root-права. И даже если у вас старая версия SuperSU, которая не исключает возможность работать на ней, то проблемы, связанные с выполнением каких-либо операций, однозначно возникнут. Поэтому обновить, или вернее, правильно установить бинарный файл Su придётся в любом случае.

    Для этого нам понадобится скачать и установить программу Baidu Root . В Гугл Плее этого приложения нет, так что можно, открыв любой браузер, найти эту утилиту, или нажав на указанную ссылку, скачать прямо с этой страницы. После чего начнётся загрузка ark-файла, процесс которой будет виден на дисплее:

    Теперь нам нужно открыть файл и нажать кнопку «Установить». На запрос о разрешении установки, нажимаем кнопку «ОК»:

    Затем откроется окошко с информацией о данных, к которым приложение получит доступ, и предупреждение об ответственности самого пользователя. Соглашаемся со всем, и вот, установка Baidu Root завершена:

    После установки внизу дисплея справа и слева появятся две кнопки, жмём на правую, после чего, по центру экрана появится синий монитор, где будет указана ваша модель Андроид, и голубая кнопка по центру (получить root) , нажимаем на неё, после чего произойдёт перезагрузка аппарата. Теперь пробуем запустить приложение SuperSU. От Baidu Root появится запрос на Root-доступ (права Суперпользователя), предоставляем. Далее появится запрос на обновление бинарного файла SU, нажимаем кнопку «Продолжить»:

    Затем программа предложит способ, которым устанавливать файл SU, выбираем «Нормально». Начнётся процесс установки, о чём нам сообщит система, и венчает все наши усилия опять же сообщение от системы, что установка завершилась успешно, жмём «ОК»:

    Всё, процедура завершена, и мы можем в полной мере пользоваться программой SuperSu и использовать все инструменты, имеющиеся в арсенале программы, в том числе и проводить т.н. временный ‘unroot’ на своём устройстве.

    Как установить бинарный файл Su на Андроид с помощью кастомного Recovery

    Описанный выше способ не решил проблему? Что ж, такое возможно, особенно это может касаться моделей HTC. В таком случае, придётся воспользоваться кастомным (альтернативным) рекавери. И если он у вас ещё не установлен, но желание стать продвинутым пользователем ОС Android присутствует, то установить его рано или поздно придётся. Потому, что этот инструмент позволит выполнять множество необходимых операций: создавать резервные копии, устанавливать системные обновления или перепрошивать свой Андроид другой версией операционки (ROM) и т.д.

    Мы не станем сейчас рассказывать, как установить кастомное Recovery, потому что, это тема отдельного разговора, и если она вам интересна, пишите, и мы расскажем во всех подробностях, как выполнить эту операцию.

    Сейчас же мы будем исходить из того, что вы в теме и вернёмся к нашему вопросу. То есть, если у вас есть кастомное рекавери (или вы знаете, как его установить), то смотрим на последний скриншот, и вместо кнопки «Нормально », нажимаем «CWM/TWRP ». После окончания процедуры, перезагружаем смартфон, после чего, вместе с обновлением системы, обновится и бинарный файл Su.

    Как установить файл SU через командную строку

    Если оба способа не помогли установить (обновить) файл SU, то ситуация осложняется, правда не фатально. Следующий способ, о котором мы расскажем, ориентирован на достаточно продвинутых пользователей, которые имеют опыт работы с командной строкой и знакомы с файловой структурой OS Android.

    Итак, наши действия:

    Качаем приложения Terminal Emulator for Android и Root Browser . Затем, скачиваем архив updatesu.zip , разархивируем его и перемещаем папку updatersu на SD-карту или внутреннюю память своего устройства Андроид.

    Теперь запускаем Root Browser , заходим в папку updatersu и копируем следующие файлы: (.has_su_daemon ) (.installed_su_daemon ) (install-recovery.sh ) в папку /system/etc

    После этого нам нужно для этих файлов задать верные права:

    Затем нам надо перейти в следующую папку, а именно /system/bin и создать папку .ext и задать для неё права:

    Следующим шагом копируем файл su, находящийся в папке /system/xbin в только что созданную папку (/system/bin/.ext ), переименовываем файл su, поставив перед названием точку (.su) и задаём для него права:

    Нам осталось запустить приложение Terminal Emulator for Android и ввести следующие команды:

    Теперь перезагружаемся и снова пробуем обновить бинарный файл su с помощью кнопки «Нормально» в программе SuperSu (см. выше).