Как найти указатель на файл

Указатель на файл

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

FILE
*file_pointer;

Имя
структуры FILE говорит программе о том,
что определяемая переменная является
указателем именно на файловую структуру.
Звездочка предписывает создать указатель
с соответствующим именем переменной.

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

FILE
*infile, *outfile;

Как открыть файл

Связь
между программой и файлом устанавливается
при помощи функции fopen(), синтаксис
которой показан на рис.12.3.

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


Рис.
12.3. Синтаксис функции fopen()

определенными
правилами. Например, в операционной
системе MS-DOS имя файла может состоять
максимум из восьми символов, плюс
расширение имени, состоящее не более
чем из трех символов (расширение не
является обязательным элементом). Если
вы хотите вывести информацию на печатающее
устройство, а не в дисковый файл, в
качестве имени файла в кавычках
указывается «PRN». При этом автоматически
осуществляется вывод данных на принтер.

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

r
— Указывает на то, что будет выполняться
чтение
информации из файла в память компьютера.
Если файл к этому моменту не существует
на диске, программа сообщит об ошибке
выполнения.

w
— Указывает на то, что будет выполняться
запись
данных на диск или вывод на принтер.
Если файл к этому моменту не существует,
операционная система создаст его. Если
файл уже существует на диске, вся
записанная в нем на данный момент
информация будет уничтожена.

a
— Указывает на то, что следует добавить
информацию в
конец файла. В случае отсутствия файла,
операционная система создаст его. Если
он существует, выводимые новые данные
будут добавлены в конец файла без
уничтожения текущего содержимого.

Компиляторы
Си++ и многие компиляторы Си стандарта
ANSI позволяют открывать файл
одновременно и для чтения, и для
записи. Для этого в аргументе функции
указываются режимы доступа «r+»,
«w+» или «a+».

Например,
если вы хотите создать файл с именем
CD.DAT для хранения картотеки коллекции
компакт-дисков, вы должны использовать
следующие инструкции:

FILE
*cdfile;

cdfile
= fopen(«CD.DAT», «w»);

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

FILE
*cdfile;

cdfile
= fopen(«CD.DAT», «r»);

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

Если
вы хотите распечатать информацию о
вашей коллекции на принтере, используйте
следующую последовательность инструкций:

FILE
*cdfile;

cdfile
= fopen(«PRN», «w»);

Учтите,
что вывод информации на принтер возможен
только с режимом доступа «w».

Как Си/Си++ работает с файлами

Си
сохраняет сведения о текущей позиции
чтения и записи в файле, используя
специальный указатель.

При
чтении информации из файла, указатель
определяет следующие данные, которые
должны быть считаны с диска. Когда файл
открывается впервые с использованием
режима доступа «r», указатель
помещается на первый символ файла. При
выполнении очередной операции чтения,
указатель перемещается к следующей
порции данных, которые должны быть
прочитаны. Величина шага перемещения
при этом зависит от количества информации,
которая считывается за один прием
(рис.12.4).
Если за один раз считывается только
один символ, указатель передвинется на
следующий символ, если читается целая
структура, указатель перейдет на
следующую структуру. Как только вся
информация прочитана из файла, указатель
попадает на специальный код, называемый
символом
конца файла
*.
Попытка продолжения чтения после
достижения конца файла приведет к ошибке
выполнения.

________________________

*
Наличие символа конца файла на самом
деле вовсе не является обязательным.
(Прим.ред.)


Рис.
12.4. Указатель сохраняет сведения о
текущей позиции в файле

Если
файл открывается с режимом доступа «w»,
указатель также помещается в начало
файла, так что первые введенные данные
будут помещены в начало файла. При
закрытии файла после введенного массива
данных будет добавлен символ конца
файла. Если файл к моменту его открытия
с использованием режима доступа «w»
уже существует, все содержащиеся в нем
данные затираются и «поверх» них
записывается новая информация, введенная
с помощью процедуры записи. Любые данные,
которые могут остаться не уничтоженными,
располагаются после нового символа
конца файла, так что к ним уже нельзя
будет обратиться при следующем чтении
данных из файла. Таким образом, любая
попытка записи данных в существующий
файл с использованием режима доступа
«w» приведет к уничтожению хранящейся
в нем на данный момент информации. Это
произойдет даже в том случае, если файл
будет просто открыт и закрыт, без записи
каких-либо данных.

Если
файл открывается с использованием
режима доступа «a», указатель
помещается на символ конца файла. Новые
данные, которые записываются в файл,
размещаются после уже существующих
данных, а затем добавляется символ конца
файла.

Соседние файлы в папке C++

  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #
  • #

В С++ рекомендуется использовать iostream (cin, cout, etc). Это совершенно другая библиотека, которая не имеет прямого отношения к stdio (FILE* etc). И, в общем случае, они никак не совместимы друг с другом.

Однако, Вас никто не принуждает использовать iostream в Вашем С++ проекте. Используйте C++ + stdio. Проблема будет если Вам надо использовать две разных библиотеки, одна из которых принимает FILE *, а другая iostream, и Вам для чего-то нужно передать один и тот же файл из одной в другую.

ктстаи, праивльнее использовать в С++

In this article, we will learn how to operate over files using a C program. A single C file can read, write, move, and create files in our computer easily using a few functions and elements included in the C File I/O system. We can easily manipulate data in a file regardless of whether the file is a text file or a binary file using functions like fopen(), fclose(), fprintf(), fscanf(), getc(), putc(), getw(), fseek(), etc.

What are files in C?

A file is used to store huge data. C provides multiple file management functions like file creation, opening and reading files, Writing to the file, and closing a file. The file is used to store relevant data and file handling in C is used to manipulate the data.

Types of Files in C

There are mainly two types of files that can be handled using File Handling in C as mentioned below:

  1. Text Files
  2. Binary Files

1. Text Files

 These are simple text files that are saved by the (.txt) extension and can be created or modified by any text editor. Text file stores data in the form of ASCII characters and is used to store a stream of characters.

2. Binary Files

 It is stored in binary format instead of ASCII characters. Binary files are normally used to store numeric Information (int, float, double). Here data is stored in binary form i.e, (0’s and 1’s).

C Files Operations

C Files can perform multiple useful operations that are mentioned below:

  1. Creation of a new file (fopen with attributes as “a” or “a+” or “w” or “w+”).
  2. Opening an existing file (fopenopen).
  3. Reading from file (fscanf or fgets).
  4. Writing to a file with fprintf or fputs.
  5. Moving file pointer associated with a given file to a specific position. (fseek, rewind).
  6. Closing a file (close).

File Pointer declaration

For performing operations on the file, a special pointer called File pointer is used that can be declared as:

FILE file_ptr;

We can open the file as

file_ptr = fopen("fileName.txt", "w");

File Modes in C

The second parameter i.e, “w” can be changed according to the table below:

Opening Modes Description
r Searches file. If the file is opened successfully fopen( ) loads it into memory and sets up a pointer that points to the first character in it. If the file cannot be opened fopen( ) then it returns NULL.
rb  Open for reading in binary mode. If the file does not exist then fopen( ) will return NULL.
w Searches file. Contents are overwritten if the file exists. A new file is created if the file doesn’t exist. Returns NULL, if unable to open the file.
wb Open for writing in binary mode. Its contents are overwritten if the file exists, else the file will be created. 
a Searches file. If the file is opened successfully fopen( ) loads it into memory and sets up a pointer that points to the last character in it. If the file doesn’t exist, a new file is created. Returns NULL, if unable to open the file.
ab  Open for append in binary mode. Data is added to the end of the file. A file will be created if it does not exist.
r+ Searches file. It is opened successfully fopen( ) loads it into memory and sets up a pointer that points to the first character in it. If it is unable to open the file it Returns NULL.
rb+  Open for both reading and writing in binary mode. fopen( ) returns NULL if the file does not exist.
w+ Searches file. Its contents are overwritten if the file exists. A new file is created if the file doesn’t exist. Returns NULL, if unable to open the file.
wb+ Open for both reading and writing in binary mode. Contents are overwritten if the file exists. It will be created if the file does not exist.
a+ Searches file. If the file is opened successfully fopen( ) loads it into memory and sets up a pointer that points to the last character in it. If the file doesn’t exist, a new file is created. Returns NULL, if unable to open the file.
ab+ Open for both reading and appending in binary mode. A file will be created if the file does not exist.

If you want to handle binary files then access modes like “rb”, “wb”, “ab”, “rb+”, r+b”, “wb+”, “w+b”, “ab+”, “a+b” will be used mostly.

Opening a file in C

To perform the opening and creation of a file in c we can use the fopen() function which comes under stdio.h header file.

Syntax:

p = fopen("fileopen", "mode");

Example:

p = fopen("Hello.txt", r);

Creating a File in C

As now we know how to open a file using fopen() now the question arises about creation. The creation of a file is as simple as opening a file. As, if the while opening a file for writing or appending is done with either write(“w”) or append(“a”) mode then in the case where the file doesn’t exist a new file is created.

Example:

C

#include <stdio.h>

#include <stdlib.h>

int main()

{

    FILE* ptr;

    ptr = fopen("./Hello.txt", "w");

    if (ptr == NULL) {

        printf("Error Occurred While creating a "

               "file !");

        exit(1);

    }

    fclose(ptr);

    printf("File creatednn");

    return 0;

}

Output:

The output of the Creating a File in C

File Created:

Hello.txt file created using the C program

Writing a File in C

1. Writing to a text file in C

fprintf() and fscanf() are used to read and write in a text file in C programming. They expect a pointer to the structure FILE since they are file versions of print() and scanf().

C

#include <stdio.h>

#include <stdlib.h>

int main()

{

    FILE* ptr;

    ptr = fopen("./Hello.txt", "w+");

    if (ptr == NULL) {

        printf("Error Occurred While writing to a text "

               "file !");

        exit(1);

    }

    char str[] = "This is all the Data to be inserted in "

                 "File by GFG.";

    fputs(str, ptr);

    fclose(ptr);

    printf("Data Written Inside the filenn");

    return 0;

}

Output:

The output of Writing to a text file in C

File Created:

Writing to a text file in C

The above program takes a string from a user and stores it in text_file.text.After compiling this program a text file named temp_text.txt will be created in the C_Program folder. Inside the file, we can see the string that we entered.

2. Writing to a Binary File

fwrite() function takes four arguments address of data, size of the data which is to be written on the disk, number of data types, and a pointer to the file where we want to write.

Syntax:

fwrite(const void *ptr,size_of_elements,number_of_elements, FILE *a_file);

Below is the C program to write to a binary file:

C

#include <stdio.h>

#include <stdlib.h>

struct Num {

    int n1, n2;

};

int main()

{

    int n;

    struct Num obj;

    FILE* fptr;

    if ((fptr = fopen("temp.bin", "wb")) == NULL) {

        printf("Error! opening file");

        exit(1);

    }

    for (n = 1; n < 10; n++) {

        obj.n1 = n;

        obj.n2 = 12 + n;

        fwrite(&obj, sizeof(struct Num), 1, fptr);

    }

    fclose(fptr);

    printf("Data in written in Binary Filenn");

    return 0;

}

Output: 

The output of Writing to a Binary File

Image of created file:

.bin file created with the data

Note: fread() is used to read from a binary file and fwrite() is used to write to a file on the disk.

Reading File in C

1. Reading text files in C

Below is the C program to read the contents from the file:

C

#include <stdio.h>

#include <stdlib.h>

int main()

{

  char str[80];

  FILE* ptr;

  ptr = fopen("Hello.txt", "r");

  if (ptr == NULL) 

  {

    printf("Error While opening file");

    exit(1);

  }

  if(fgets(str, 80, ptr) != NULL)

  {

    puts(str);

  }

  fclose(ptr);

  return 0;

}

Output:

The output of Reading text files in C

2. Reading from a Binary File

fread() function also takes four arguments that are similar to fwrite() function in C Programming.

Syntax:

fwrite(const void *ptr,size_of_elements,number_of_elements, FILE *a_file);

Below is the C program to read from a binary file:

C

#include <stdio.h>

#include <stdlib.h>

struct Num 

{

    int n1, n2;

};

int main()

{

  int n;

  struct Num obj;

  FILE* fptr;

  if ((fptr = fopen("temp.bin", "rb")) == NULL) 

  {

    printf("Error! opening file");

    exit(1);

  }

  for (n = 1; n < 10; ++n) 

  {

    fread(&obj, sizeof(struct Num), 1, fptr);

    printf("n1: %dtn2: %dn", obj.n1, obj.n2);

  }

  fclose(fptr);

  return 0;

}

Output:

The output of Reading from a Binary File

Explanation: In the above program, we have read the same file GFG.bin and are looping through records one by one. We read a single Num record of Num size from the file pointed by *fptr into the structure Num. We’ll get the same record that we inserted in the previous program. 

Moving File Pointers to Specific Positions

fseek() and rewind() are the two methods in C programming that can be used to move the file pointer. Let us check both methods:

1. fseek() in C Programming

fseek() function is used to set the file pointer to the specified offset and write data into the file.

Syntax:

int fseek(FILE *stream, long int offset, int whence);

Here,

  • whence can be SEEK_SET, SEEK_CUR and SEEK_END.
  • SEEK_END: It denotes the end of the file.
  • SEEK_SET: It denotes starting of the file.
  • SEEK_CUR: It denotes the file pointer’s current position.

Below is the C program to implement fseek():

C

#include <stdio.h>

#include <stdlib.h>

int main()

{

    char str[80];

    FILE* ptr;

    ptr = fopen("Hello.txt", "w+");

      fputs("Welcome to GeeksforGeeks", ptr);

    fseek(ptr, 11, SEEK_SET);

    fputs("Programming  ", ptr);

    fclose(ptr);

    ptr = fopen("Hello.txt", "r+");

    if (fgets(str, 80, ptr) != NULL) {

        puts(str);

    }

    fclose(ptr);

    return 0;

}

Output:

The output of  fseek() in C

Image of the File:

2. rewind() in C

rewind() function sets the file pointer to the beginning of the file. 

Syntax:

void rewind(FILE *stream);

Below is the C Program to implement rewind():

C

#include <stdio.h>

#include <stdlib.h>

int main()

{

    char str[200];

    FILE* ptr;

    ptr = fopen("Hello.txt", "w+");

    fputs("Welcome to GeeksforGeeks", ptr);

    fclose(ptr);

    ptr = fopen("Hello.txt", "r+");

    if (fgets(str, 200, ptr) != NULL) {

        puts(str);

    }

    rewind(ptr);

    if (fgets(str, 200, ptr) != NULL) {

        puts(str);

    }

    fclose(ptr);

    return 0;

}

Output:

The output of rewind() in C

Image of the File:

File after running the program

FAQs on C File I/O

1. How to open a file in C?

File in C can be opened using file pointer and fopen function. In the first step, we need to declare the file pointer and in the second step we can use fopen with the name of the file to be opened and the mode(read, write, append) for using the file.

Example:

FILE file_ptr;
file_ptr = fopen("fileName.txt", "w");

2. How to create a file in C?

The file can be created using two modes: append and write. We need to simply open the file with either mode to create the file.

3. How to read a file in C?

File in C can be read by opening the file in read mode. And we can get strings from the file using the fgets function.

4. How to write to a file in C?

File in C can be read by opening the file in read mode. And we can get strings from the file using the fputs function.

5. What is the use of fseek() in C?

fseek() is used for moving file pointer associated with a given file to a specific position in a file.

6. What are modes in C file io?

Modes in C file IO defines the functionality of the file pointer,i.e. means whether it can read, write, append, etc in a file.

7. What are different operations which can be performed on a file in C?

There are multiple operations that can be performed in a file which are creating, opening, reading, writing, and moving.

Вы здесь

Указатель на файл

Указатель на файл — это нечто, объединяющее файловую систему ANSI С. Указатель на файл — это указатель на информацию, определяющую различные параметры файла, включая его имя, состояние и текущую позицию. В принципе, указатель на файл идентифицирует конкретный дисковый файл и используется потоком для выполнения операций ввода/вывода. Указатель на файл — это переменная-указатель типа FILE. Чтобы прочитать или записать файлы, программе надо использовать указатели на файлы. Для создания файловой переменной-указателя используется оператор типа:

FILE *fp;

Текстовые блоки в исполняемом elf-файле как правило хранятся в секции .rodata (read only data). Ссылки (указатели) на начальные адреса позиций используемых текстовых блоков находятся в секции инструкций .text. Следовательно, если надо переместить начало блока (вправо или влево), надо соответственно изменить указатели адресов.

С этой проблемой часто сталкиваются русификаторщики программ. Например, слово «сохранить» длиннее, чем его английский аналог «save». Между соседними текстовыми блоками должен быть разделитель (хотя бы один нулевой байт). Если изменяемый текстовый блок помещается в отведенный размер (при этом должен остаться как минимум один нулевой байт перед следующим блоком), проблем нет — можно править. Но если конец изменяемого блока заходит на начало соседней (справа) позиции, придется изменять указатели на эту позицию.

Пример, с которым работал я: исполняемый elf-файл, формат — big endian, процессор — MIPS32:

             0 1 2 3  4 5 6 7  8 9 A B  C D E F                                      

  4d6a30:   6d696d6f 00000000 73686f77 73734755     mimo....showssGU
  4d6a40:   49000000 64736c56 65727369 6f6e0000     I...dslVersion..
  4d6a50:   68746d6c 63686172 73657400 49534f2d     htmlcharset.ISO-
  4d6a60:   38383539 2d310000 4249472d 35000000     8859-1..BIG-5...
  4d6a70:   53757043 484c616e 67000000 636f6e6e     SupCHLang...conn
  4d6a80:   65637449 6e666f00 636f6e63 6f756e74     ectInfo.concount
  1. Надо сдвинуть влево блок «BIG-5». Слева есть два нулевых байта, значит двигать можно. Начальная позиция 4d6a68 должна измениться на 4d6a67. Надо найти указатель на эту позицию в секции .text Можно сделать это вручную (поискать HEX-значение 6A 68). Но лучше использовать дизассемблер (например IDA PRO). Дизассемблируем и находим соответствующую позицию в секции .rodata:

    .rodata:004D6A66 byte_4D6A66: .byte 0 # DATA XREF: cgiGetVar+F8r

    .rodata:004D6A67 .align 2

    .rodata:004D6A68 aBig5: .ascii «BIG-5″<0> # DATA XREF: cgiGetVar+C4o

    .rodata:004D6A68 # cgiGetVar+C8r …

    .rodata:004D6A6E .align 4

    .rodata:004D6A70 aSupchlang: .ascii «SupCHLang»<0> # DATA XREF: cgiGetVar+130o

    .rodata:004D6A7A .align 2

  2. Проходим по ссылке (cgiGetVar +...) и попадаем в соответствующий раздел секции
    .text:

    .text:00489060 la $v0, 0x4D0000

    .text:00489064 la $v0, 0x4D0000

    .text:00489068 addiu $v1, $v0, (aBig5 — 0x4D0000) # «BIG-5»

    .text:0048906C lw $v0, (aBig5 — 0x4D0000)($v0) # «BIG-5»

    .text:00489070 lbu $a0, (aBig5+5 — 0x4D6A68)($v1)

    .text:00489074 lbu $v1, (aBig5+4 — 0x4D6A68)($v1)

    .text:00489078 swl $v0, 0($s1)

    .text:0048907C swr $v0, 3($s1)

    .text:00489080 sb $a0, 5($s1)

    .text:00489084 b loc_48A190

    .text:00489088 sb $v1, 4($s1)

  3. Находим соответствующий адрес HEX редактором. Адрес 00489068 ищем как 00089068:

               0  1  2  3  4  5  6  7   8  9  A  B  C  D  E  F  
    00089050  8f 82 8a 1c 8c 43 00 00  24 02 00 01 14 62 00 0b  |.....C..$....b..|
    00089060  8f 82 80 28 8f 82 80 28  24 43 6A 68 8c 42 6a 68  |...(...($Cjh.Bjh|
    00089070  90 64 00 05 90 63 00 04  aa 22 00 00 ba 22 00 03  |.d...c..."..."..|
    00089080  a2 24 00 05 10 00 04 42  a2 23 00 04 8c 43 6a 5c  |.$.....B.#...Cj|
    00089090  24 42 6a 5c 8c 44 00 04  aa 23 00 00 90 45 00 0a  |$Bj.D...#...E..|
    000890a0  90 46 00 08 90 42 00 09  ba 23 00 03 aa 24 00 04  |.F...B...#...$..|
    000890b0  ba 24 00 07 a2 25 00 0a  a2 26 00 08 10 00 04 34  |.$...%...&.....4|
    000890c0  a2 22 00 09 8f 85 80 28  8f 99 89 cc 02 40 20 21  |.".....(.....@ !|
    

    IDA PRO к адресу позиции добавляет 4, вместо 0 в привычном HEX.

  4. Видим сразу два (!) указателя на соответствующую позицию (D6A68) — 24 43 6A 68 8c 42 6a 68. Меняем оба на 24 43 6A 67 8c 42 6a 67. Сохраняем файл. Можно запускать.

В приведенном примере использован файл формата big endian — байты пишутся прямым порядком (и без смещения на величину заголовка). Если есть смещение, его надо учитывать при поиске и обозначении позиций. Если используется формат little endian, надо писать байты в обратном порядке.

В статье «Работаем со смещениями — расширяем горизонты!»[архив] есть похожий пример, который и вдохновил на изменение elf файла.

Понравилась статья? Поделить с друзьями:
  • Как составить доверенность на оплату
  • Как исправить 2 по русскому языку по диктанту
  • Как исправить ошибку please wait
  • Как найти участников дом 2 в контакте
  • Как найти тему для трека