Форум программистов, компьютерный форум, киберфорум
C++ Builder
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
 
Рейтинг 4.70/89: Рейтинг темы: голосов - 89, средняя оценка - 4.70
7 / 7 / 0
Регистрация: 09.10.2011
Сообщений: 38

Сохранение файла

13.10.2011, 23:26. Показов 18787. Ответов 21
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Вобщем так... Есть форма, на ней 2 кнопки. Одна открывает файл(оупенДиалог1), производит там нужные изменения и закрывает. А вторая должна сохранить.. Но не хочет( какой там код должен быть на кнопке?)
0
Programming
Эксперт
39485 / 9562 / 3019
Регистрация: 12.04.2006
Сообщений: 41,671
Блог
13.10.2011, 23:26
Ответы с готовыми решениями:

Создание/сохранение файла
Как создать файлы с помощью цикла, чтобы имена файлов менялись... TStringList *list = new TStringList; for ( int i = 1 ; i <= 4...

Открытие и сохранение файла
Добрый вечер. Есть код void __fastcall TForm1::N3Click(TObject *Sender) { TTabSheet* TabSheet1 = new...

Создание/сохранение файла
Пишет, что не может создать файл void __fastcall TForm1::Button7Click(TObject *Sender) { String FileName =...

21
 Аватар для __bool
288 / 229 / 27
Регистрация: 13.06.2010
Сообщений: 744
13.10.2011, 23:28
Какой файл открываете OpenDialog'ом? В переменную какого типа его считываете?
0
7 / 7 / 0
Регистрация: 09.10.2011
Сообщений: 38
13.10.2011, 23:31  [ТС]
Файл .bin , считываю в AnsiString
0
 Аватар для __bool
288 / 229 / 27
Регистрация: 13.06.2010
Сообщений: 744
13.10.2011, 23:36
Я бы сделал так:
C++
1
2
3
4
TStringList* strList = new TStringList; создаем
strList->LoadFromFile("имя файла из OpenDialog"); // открываем
//strList->Text; тут ваш текст
strList->SaveToFile("имя конечного файла");// сохраняем
0
7 / 7 / 0
Регистрация: 09.10.2011
Сообщений: 38
13.10.2011, 23:50  [ТС]
Не, там как получается... открывается одной функцие, сохраняется другой. и вот та которая сохраняет она похоже не понимает что ей надо сохранить)
0
 Аватар для __bool
288 / 229 / 27
Регистрация: 13.06.2010
Сообщений: 744
13.10.2011, 23:52
А что мешает открывать этой вашей "одной" функцией записывая файл в TStringList??))
А потом нормально сохранить его как я показал?
Если действительно там прям особый случай, код в студию!
0
7 / 7 / 0
Регистрация: 09.10.2011
Сообщений: 38
13.10.2011, 23:55  [ТС]
да с собой нету...) что делает TStringList ?
0
 Аватар для __bool
288 / 229 / 27
Регистрация: 13.06.2010
Сообщений: 744
14.10.2011, 00:00
Цитата Сообщение от Fitz Посмотреть сообщение
да с собой нету...) что делает TStringList ?
Вообще для этих целей Google..
TStringList - полезный тип класса. Он чрезвычайно полезен для многих видов обработок списков. Элементы в строковом списке могут быть вставлены, перемещены и отсортированы.

Список может быть сформирован строка за строкой, или загружен из большой строки разделенной запятой или даже из текстового файла. TStringList происходит от TStrings. Вы можете использовать и TStrings, но это не рекомендуется, так как он не полный - некоторые из его методов абстрактны. TStringList осуществляет эти абстрактные методы (Clear, Delete и Insert). Мы рассмотрим основные свойства и методы TStringList, включая полученные из TStrings.

Свойство Count
Возвращает число строк в списке.

Свойство Capacity

Устанавливает или получает текущую вместимость строкового списка. Вы можете управлять этой вместимостью по необходимости.

Свойство Strings
Получает или корректирует строку по данному индексу в списке (первый элемент списка имеет индекс 0).

Обратите внимание, что свойство Strings является свойством, заданным по умолчанию. Это означает, что вы можете использовать его без его указания:

myName = names->Strings[4];

является эквивалентным:

myName = names[4];

Свойство Text
Устанавливает или получает список в виде большой строки. Эта строка будет содержать каждую строку закончивающуюся комбинацией символов перевода каретки и перевода строки (CRLF). Полезно для загрузки из визуального объекта, который может содержать многочисленные строки текста.

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

Cвойство DelimitedText
Получает или устанавливает список через большую строку. Эта строка содержит список строк разделенных значением Delimiter (по умолчанию - запятая). Строки, содержащие вложенные пробелы должны быть заключены в QuoteChar (по умолчанию - ").

Свойство QuoteChar
Используется для замыкания строк, которые имеют вложенные пробелы при использовании DelimitedText.

Свойство Delimiter
Используется для разделения строк при использовании DelimitedText
. Свойство Names
Строки в строковом списке могут быть обработаны, как пары название/значение, как во втором примере кода. Каждая строка не должна иметь никаких внедренных пробелов, и содержать знак =. Это очень полезное понятие. См. свойства Value и ValueFromIndex, и метод IndexOfName.

Свойство Values
Возвращает значение для данного названия, когда используются строки пары название/значение (см. выше).

Свойство ValueFromIndex
Возвращает значение по индексу строки (начинается с 0), когда используются пары название/значение.

Свойство CaseSensitive
Когда true, Delphi обрабатывает строки чувствительно к регистру при выполнении некоторых операций, таких как Sort.

Свойство Duplicates
Это свойство может иметь одно из следующих перечислимых TDuplicates значений:

dupIgnore Игнорирует (отбрасывает) дубликаты
dupAccept Позволяют дубликаты
dupError Выбрасывает исключение, если имеются дубликаты


Свойство Sorted
Когда true, все строки будут добавляться в свою позицию отсортированной последовательности. Когда false, они будут добавляться в конец. См. также метод Sort.

Свойство Objects
Возвращает объект, связанный со строкой по данному индексу, если он существует.

Метод Add
Добавляет данную строку в список, возвращая ее позицию в списке (начинается с 0).

Метод Append
Так же как и Add, но без возвращения индексного значения.

Метод Insert
Вставляет строку в заданную индексом позицию. Позиция 0 вызовет вставку в начало.

Метод Delete
Удаляет строку по данному индексу.

Метод Clear
Удаляет все строки из списка.

Метод Move
Перемещает строку из одной позиции в другую, сдвигая другие строки соответственно.

Метод Exchange
Перестанавливает две строки в списке, идентифицированные по их индексным позициям.

Метод IndexOf
Получает индекс позиции строки в списке соответствующей данной строке. Если строка не найдена, то возвращается -1.

Метод IndexOfName
Получает индекс позиция первой пары название/значение строки, где название соответствует данной строке. Если не найдена - возвращается -1.

Метод Find
То же самое, что и IndexOf, но с использованием списков сортированных строк.

Метод Sort
Если Sorted является ложным, то это вызовет сортировку списка.

Метод AddStrings
Добавляет строки из другого списка.

Метод Assign
Заменяет текущий список содержанием другого списка.

Метод LoadFromFile
Очень полезный метод, загружает строковый список из текстового файла. Каждая текстовая строка (законченая CRLF - см. DelimitedText) становится строкой списка.

Метод SaveToFile
Сохраняет строковый список в текстовый файл.
2
7 / 7 / 0
Регистрация: 09.10.2011
Сообщений: 38
14.10.2011, 08:30  [ТС]
вот, что еще надо? Сорри, могу только так выложить, ибо с телефона
Вложения
Тип файла: txt 11111111.TXT (815 байт, 97 просмотров)
0
return (true);
 Аватар для mimicria
1977 / 1112 / 221
Регистрация: 19.04.2011
Сообщений: 2,346
14.10.2011, 08:57
Цитата Сообщение от Fitz Посмотреть сообщение
Ff1 = SaveDialog1->FileName;
SaveDialog1->SaveToFile(Ff1);
Ну задали вы имя файла для сохранения, а что сохранили то?
Где результат работы prog, что сохранять собираетесь?

Добавлено через 3 минуты
Вам уже предлагали сделать так:
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void __fastcall TForm1::BtnFileOpenClick(TObject *Sender)
{
    if (OpenDialog1->Execute())
    {
     TStringList *file = new TStringList;
     file->LoadFromFile(OpenDialog1->FileName);
     // тут делаем дальше с файлом что надо, он в StringList
    }
 
}
 
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnFileOutClick(TObject *Sender)
{
     Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnFileSaveClick(TObject *Sender)
{
    if (SaveDialog1->Execute())
    {
     file->SaveToFile(SaveDialog1->FileName); // сохранили в новый файл  
     delete file;
    } 
}
1
7 / 7 / 0
Регистрация: 09.10.2011
Сообщений: 38
14.10.2011, 09:05  [ТС]
file->SaveToFile(SaveDialog1->FileName);
improper us of typedef "file"
0
 Аватар для cpp_developer
20124 / 5691 / 417
Регистрация: 09.04.2010
Сообщений: 22,546
Записей в блоге: 1
14.10.2011, 09:14
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
#pragma resource "*.dfm"
TForm1 *Form1;
TStringList *myfile;
myfile = new TStringList;
 
//...
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnFileOpenClick(TObject *Sender)
{
  if (OpenDialog1->Execute()) {
    myfile->LoadFromFile(OpenDialog1->FileName);
   // тут делаем дальше с файлом что надо, он в StringList
  }
}
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnFileSaveClick(TObject *Sender)
{
  if (SaveDialog1->Execute()) {
    myfile->SaveToFile(SaveDialog1->FileName); // сохранили в новый файл  
  } 
}
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnFileOutClick(TObject *Sender)
{
  delete myfile;
  myfile = NULL;
  Close();
}
//---------------------------------------------------------------------------
1
return (true);
 Аватар для mimicria
1977 / 1112 / 221
Регистрация: 19.04.2011
Сообщений: 2,346
14.10.2011, 09:19
Цитата Сообщение от Fitz Посмотреть сообщение
file->SaveToFile(SaveDialog1->FileName);
improper us of typedef "file"
Дада, file надо объявлять глобальной переменной. LK поправил
2
 Аватар для cpp_developer
20124 / 5691 / 417
Регистрация: 09.04.2010
Сообщений: 22,546
Записей в блоге: 1
14.10.2011, 09:31
и имена давать свои, а не соотносящиеся с определениями ИДЕ, имхо.
1
return (true);
 Аватар для mimicria
1977 / 1112 / 221
Регистрация: 19.04.2011
Сообщений: 2,346
14.10.2011, 09:45
Цитата Сообщение от LK Посмотреть сообщение
и имена давать свои, а не соотносящиеся с определениями ИДЕ, имхо.
file не ключевое слово.
0
 Аватар для cpp_developer
20124 / 5691 / 417
Регистрация: 09.04.2010
Сообщений: 22,546
Записей в блоге: 1
14.10.2011, 10:08
там о ключевых отсуствовало, ключевые слова и определения системы и/или ИДЕ - разные вещи, имхо
1
return (true);
 Аватар для mimicria
1977 / 1112 / 221
Регистрация: 19.04.2011
Сообщений: 2,346
14.10.2011, 10:14
Цитата Сообщение от LK Посмотреть сообщение
определения системы и/или ИДЕ
И что, file подпадает под определения системы или ИДЕ? Тогда почему с ним всё компилируется и работает? Где можно взять определения конкретной системы/ИДЕ, в частности BCB?
1
 Аватар для cpp_developer
20124 / 5691 / 417
Регистрация: 09.04.2010
Сообщений: 22,546
Записей в блоге: 1
14.10.2011, 10:24
да я не спорю, просто так не делаю
Файл как объект API операционной системы
Определение: файл
1
7 / 7 / 0
Регистрация: 09.10.2011
Сообщений: 38
16.10.2011, 21:57  [ТС]
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
//---------------------------------------------------------------------------
 
#include <vcl.h>
#pragma hdrstop
 
#include "APLIC.h"
#include "Unit1.h"
 
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
 
TForm1 *Form1;
 
//---------------------------------------------------------------------------
__fastcall TForm1::TForm1(TComponent* Owner)
    : TForm(Owner)
{
 
}
//---------------------------------------------------------------------------
 
void __fastcall TForm1::BtnFileOpenClick(TObject *Sender)
{
    AnsiString (Ff1);
 
    if (OpenDialog1->Execute())
    {
        Ff1 = OpenDialog1->FileName;
        char *F1 = Ff1.c_str();                                                     
    prog(F1);
    }
 
 
}
 
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnFileOutClick(TObject *Sender)
{
     Close();
}
//---------------------------------------------------------------------------
void __fastcall TForm1::BtnFileSaveClick(TObject *Sender)
{
    AnsiString (Ff1);
 
    if (SaveDialog1->Execute())
    {
        Ff1 = SaveDialog1->FileName;
       // SaveToFile(SaveDialog1->FileName);
    }
}
//---------------------------------------------------------------------------

Вот модуль

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
//---------------------------------------------------------------------------
 
#pragma hdrstop
 
#include <stdio>
#include <iostream>
#include <string>
#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
 
int hex(int w)
{
    return w-55;
}
 
//---------------------------------------------------------------------------
 
int HexToInt(char* str)
{
 
    int i, Int=0;
    for (i = 0; i<4; i++)
    if (str[i] < 'A')
    {
        Int = Int * 16 + str[i] - 48;
    }
    else
        Int = Int * 16 + hex(str[i]) ;
 
    return Int;
}
 
//---------------------------------------------------------------------------
 
int prog(char* F1)
{
    FILE * file1 = fopen(F1, "rt");
    char str1[255];
    char str_1[255];
    FILE * file2 = fopen("out.bin", "wb");
    int len;
    char str_14[255];
    while (!feof(file1))
    {
        memset(str1,0,255);                     
        fgets(str1,255,file1);                   
        len = strlen(str1);                     
        if (len == 44)
        {
            memcpy(str_1,&str1[7],36);          
            char str[4];                       
 
            int i=0, q;
            while (i!=36)
            {
                str_14[4] = 0;
                memcpy(str_14,&str_1[i],4);
 
                q = HexToInt(str_14);
 
                fwrite(&q,4,1,file2);
                i = i + 4;
            }
            fwrite("\n",1,1,file2);
        }
    }
    //fclose(file2);
    return 0;
}

Не сохраняет ивсе) хоть убейте. делал и как вы писали.. не понимаю. Максимум чего я добился - сохраняет что то в файл и то, помоему он олжен быть уже создал
0
 Аватар для cpp_developer
20124 / 5691 / 417
Регистрация: 09.04.2010
Сообщений: 22,546
Записей в блоге: 1
16.10.2011, 22:19
для внеклассного чтения...
Открытие и закрытие файлов

Для работы с файлами используются указатели на структуру типа FILE, которая определена в библиотеке <stdio.h>. Объявление файлового потока выглядит так:
C++
1
FILE *имя;
Имя — это обычное имя в программе на С++, которое обозначает поток, связываемый с файлом на диске. Аналогичный аргумент передается практически всем функциям, выполняющим работу с файлами. Открыть файл и связать поток с ним можно функцией fopen(), имеющей прототип
C++
1
FILE * fopen(const char *имя_файла, const char *режим);
Имя_файла — это имя файла на диске, оно указывается единственный раз при открытии. Во всех остальных операциях участвует указатель на FILE. Количество открытых одновременно файлов ограничивается константой FOPEN_MAX, определенной в заголовке <stdio.h>.
Режим — это строка, задающая способ дальнейшей обработки файла. Режимы перечислены в табл. 10.4.

Таблица 10.4. Режимы открытия файла

Обозначение Смысл

"r" или "rt" Открыть текстовый файл для чтения. Если файл не обнаружен, функция возвращает ноль (нулевой указатель).
"w" или "wt" Создать текстовый файл для записи. Если файл существует, содержимое файла уничтожается.
"a" или "at" Открыть для добавления строк в конец текстового файла. Если файла нет, он создается.
"r+" или "r+t" Открыть существующий текстовый файл для чтения и записи.
"w+" или "w+t" Открыть новый текстовый файл для чтения и записи. Если файл существует, то его содержимое уничтожается.
"a+" или "a+t" Открыть для чтения и добавления строк в конец текстового файла. Если файла нет, он создается.
"rb" Открыть двоичный файл для чтения. Если файл не обнаружен, функция возвращает ноль (нулевой указатель).
"wb" Создать двоичный файл для записи. Если файл существует, содержимое файла уничтожается.
"ab" Открыть для добавления записей в конец двоичного файла. Если файла нет, он создается.
"r+b" Открыть существующий двоичный файл для чтения и записи.
"w+b" Открыть новый текстовый файл для чтения и записи. Если файл существует, то его содержимое уничтожается.
"a+b" Открыть для чтения и добавления записей в конец двоичного файла. Если файла нет, он создается.

Когда файл открывается в режиме дозаписи («a» или «a+»), любая операция записи выполняется в конец файла. Таким образом, если открыт существующий файл, то все ранее записанные в него данные сохраняются.
Символы t и b, если они задаются, требуется указывать после основных символов r,w,a. В справочной системе Visual C++.NET 2003 приводится следующее замечание о функции fopen():
If t or b is prefixed to the argument, the function fails and returns NULL.
Если t или b стоят перед аргументом, функция завершается неудачей и возвращает NULL.
Нужно отметить, что неправильное написание режима или имени файла никак не диагностируется компилятором при трансляции — это же константы-строки! Ошибки бывают, как правило, совершенно «дурацкие»: пропущена какая-нибудь буква или вместо английской буквы написана русская, не отличающаяся по виду, например «с». В последнем случае текст программы выглядит совершенно правильным, однако работать программа, естественно, не будет — файл просто не откроется. Поэтому нужно обязательно проверять, действительно ли файл открылся (значение указателя не равно нулю).
Пусть на дискете находится текстовый файл Readme.txt. Открыть его для чтения можно таким образом:
C++
1
FILE *fp = fopen("a:/Readme.txt", "r");
Файл закрывается с помощью функции fclose() с прототипом
C++
1
int fclose(FILE *имя);
Имя указателя должно совпадать с тем, которое использовалось при открытии. В случае успешного закрытия возвращается 0, иначе — константа EOF. Закрыть открытый выше файл Readme.txt нужно так:
C++
1
fclose(fp);
Поток по умолчанию буферизован, поэтому закрытие файла освобождает буфер. Однако имеется возможность явно указать освобождение буфера в любой момент работы программы, не закрывая файл. Для этого используется функция
C++
1
int fflush(FILE *имя);
Аналогично функции закрытия файла в случае успешной записи буфера в файл возвращается ноль, иначе — EOF.
Важнейшей функцией является функция, проверяющая, достигнут ли конец файла. Ее прототип
C++
1
int feof(FILE *имя);
Очевидно, конец файла может обнаружиться только при чтении из файла. Если в результате очередной операции ввода достигнут конец файла, система устанавливает внутренний индикатор конца файла. Этот индикатор и проверяет данная функция. Если достигнут конец файла, то функция возвращает ненулевое значение, иначе возвращается 0.
С открытием файла связана одна очень распространенная ошибка начинающих программистов, на которую хочется обратить внимание. Предположим, мы обрабатываем текстовые файлы и решили написать функцию, которая открывает файл и обрабатывает ошибки открытия. Определение такой функции может быть таким:
C++
1
2
3
4
void openfile(FILE *f, char *name)
{  if ((f=fopen(name, “rt”))==NULL)  
       fprintf(stderr, “Не могу открыть файл.\n”);  
}
Вроде бы в определении ничего крамольного не наблюдается. Однако вызов такой функции не принесет желаемых результатов.
C++
1
2
FILE *in;
openfile(in, “input.txt);
Предполагается, что функция откроет файл input.txt, и свяжет его с файловой переменной in. Если файл input.txt находится в текущем каталоге, то никаких сообщений о невозможности открыть файл не будет. Однако работать с файлом будет нельзя – первая же попытка выполнить операцию чтения приведет к аварии программы. А дело в том, что указатель передается по значению, и изменение произойдет только внутри функции openfile(). Никогда не забывайте о том, что файловую переменную, которую требуется открыть или закрыть, нужно передавать в функцию либо по указателю, либо по ссылке.

Двоичные файлы

Двоичные и текстовые файлы — это, как говорят в Одессе, «две большие разницы». Обмен данными между программой и двоичным потоком выполняется без всякого преобразования, поэтому работает быстрее. Двоичный ввод выполняется функцией fread(), имеющей следующий прототип:
C++
1
size_t fread(void *buffer, size_t size, size_t n, FILE *stream);
Тип size_t обычно определен как unsigned int. Первый параметр часто определяет массив (или указатель на динамический массив), в который будет прочитана информация; третий параметр задает размер одного элемента данных в байтах, а второй — количество читаемых элементов. Четвертый параметр определяет двоичный файл, из которого информация вводится. Общее количество считанных байтов равно size*n. Однако возвращает функция количество корректно прочитанных элементов, а не байтов.
Вывод в двоичный файл выполняется функцией fwrite(), которая имеет совершенно аналогичный прототип:
C++
1
size_t fwrite(const void *buffer, size_t size, size_t n, FILE *stream);
Функция записывает n элементов размера size в двоичный файл stream из буфера, указатель на который задается в качестве первого аргумента. Общее количество выводимых байтов равно size*n. Однако возвращает функция количество корректно записанных элементов, а не байтов.
В качестве элементов могут использоваться любые переменные любых типов, в том числе и динамические. Даже массив может быть одним-единственным элементом! Рассмотрим несколько простых примеров, аналогичных примерам для текстовых файлов (см. листинги 10.8,10.9). Создадим на диске C: каталог BinFiles и все двоичные файлы будем размещать в нем. Переделаем пример создания файла (листинг 10.12).
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
//Листинг 10.12. Создание и чтение двоичных файлов
#include <cstdio>
#include <cstdlib>
#include <ctime>
int main()
{    int m[10]={0};
    srand((unsigned)time(NULL)); // инициализация датчика случайных чисел
    FILE *stream;
/* открываем двоичный файл для записи */
    if((stream = fopen("c:/binfiles/number1.bin", "wb" )) == NULL) 
        return 1; // ошибка при открытии
/* заполняем массив m числами */
    for(int i = 0; i < 10; i++)
      m[i] = rand()%10; // случайные числа от 0 до 9
// заполняем файл number1.bin элементами-числами
    for(int i = 0; i < 10; i++)
      fwrite(&m[i], 1, sizeof(int), stream);    
    fclose(stream); // закрываем файл
/* открываем другой файл для записи */
    if((stream = fopen("c:/binfiles/number2.bin", "wb" )) == NULL) 
        return 1; // ошибка при открытии
// заполняем файл number2.bin элементом-массивом
    fwrite(m, 1, sizeof(m), stream); // массив - один элемент
    fclose(stream); // закрываем файл
// вывод второго двоичного файла на экран 
// открываем файл для чтения 
    if((stream = fopen("c:/binfiles/number2.bin", "rb" )) == NULL) 
        return 1; // ошибка при открытии
    int a = 0; // сюда вводим
// читаем второй файл поэлементно
// правильный цикл
    fread(&a, 1, sizeof(int), stream); // предварительное чтение
    while(!feof(stream)) // пока не конец файла
    { printf("%d\n", a);
      fread(&a, 1, sizeof(int), stream);
    }
    fclose(stream);
// открываем первый файл в режиме чтения
    if((stream = fopen("c:/binfiles/number1.bin", "rb" )) == NULL) 
        return 1;    
    int t[10] = {0}; // массив для чтения
// читаем первый файл как массив
    fread(t, 1, sizeof(t), stream);        
    for(int i = 0; i < 10; i++) // выводим поэлементно
        printf("%d\n",t[i]);
    fclose(stream);
char ch = getchar();
return 0;
}
В этой программе сначала создается два двоичных файла: number1.bin и number2.bin. В первый файл целые числа из массива m записываются по одному в цикле. Во второй файл весь массив записывается сразу как один элемент. Затем файлы открываются для чтения. Сначала открывается файл number2.bin (в который мы писали массив целиком), и чтение из него выполняется по одному числу. Проверка конца файла делается так же, как и для текстовых файлов. На экране видно, что чтение выполняется совершенно правильно.
Первый файл number1.bin, который записывался в цикле по одному числу, читается сразу целиком в массив t, а вывод осуществляется по одному числу. И снова мы наблюдаем на экране, что чтение выполнилось совершенно правильно. Такое «смешивание» для двоичных файлов безопасно, так как и в памяти, и на диске размеры данных равны sizeof(тип)*n, где n — количество элементов, участвующих в обмене.
Теперь добавим в конец этого примера строки, выполняющие суммирование чисел, записанных в файл number1.bin.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// суммирование чисел записанных в файле
    if((stream = fopen("c:/binfiles/number1.bin", "rb" )) == NULL) 
        return 1; // ошибка при открытии
    // читаем числа по одному из файла и считаем 
    int number, summa = 0, count = 0;
    fread(&number, 1, sizeof(int), stream);
    while(!feof(stream))
    { printf("%d\n", number);
      ++count;
      summa+=number;
      fread(&number, 1, sizeof(int), stream);
    }
    printf("%d %d\n", summa, count);
    fclose(stream);
Как видим, этот текст отличается от приведенного выше для текстовых файлов только режимом открытия и функцией ввода данных.
Так как функции посимвольного ввода/вывода fgetc() и fputc() фактически не выполняют никакого преобразования информации, то копирование двоичных файлов можно делать точно так же, как и текстовых — посимвольно. Используем функцию filecopy(), представленную в листинге 10.9.
C++
1
2
3
4
5
6
7
8
9
10
11
// копирование файлов
FILE *in, *out;
if((in = fopen("c:/binfiles/number1.bin", "rb" )) == NULL) 
{    printf ("Error input file!"); return 1; // ошибка при открытии
}
if((out = fopen("c:/binfiles/number1.new", "wb" )) == NULL) 
{    printf ("Error output file!");    return 1; // ошибка при открытии
}
filecopy(in, out); // копирование                            
fclose(in); 
fclose(out);
Соответственно и для объединения файлов можно использовать ту же функцию — все определяется режимом открытия файла.
C++
1
2
3
4
5
6
7
8
// дозапись нового файла в конец старого
if((out = fopen("c:/binfiles/number1.bin", "ab" )) == NULL) 
{    printf ("Error output file!");    return 1;    }
if((in = fopen("c:/binfiles/number1.new", "rb" )) == NULL) 
{    printf ("Error input file!");    return 1;    }
filecopy(in, out); // объединение – дозапись!
fclose(in);
fclose(out);
Для проверки правильности объединения выведем содержимое файла на экран. Используем вторую форму проверки окончания файла — внутри цикла:
C++
1
2
3
4
5
6
7
8
9
//  вывод нового файла на экран для проверки
if((stream = fopen("c:/binfiles/number1.bin", "rb" )) == NULL) 
    return 1;    
while(true)
{ fread(&a, 1, sizeof(int), stream);
  if (feof(stream)) break;
  printf("%d\n", a);
}
fclose(stream);
Размеры объектов в файле

Как мы уже знаем (см. гл. 1), размеры классов и структур в памяти зависят от выравнивания. Рассмотрим тот же вопрос с точки зрения записи в двоичный файл. Напишем простую программу (листинг 10.13), в которой просто выведем в двоичный файл несколько структур в двух режимах: с выравниванием по байту и без.
C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
//Листинг 10.13. Размеры объектов на диске
#include <cstdio>
#include <iostream>
using namespace std;
//#pragma pack(1) // выранивание по байту
int main()
{    FILE *f;
    class Empty {}; // пустой класс
    Empty t;
    if((f = fopen("c:/binfiles/binempty.bin", "wb" )) == NULL) 
        return 1; // ошибка при открытии
    fwrite(&t, 1, sizeof(t), f); // пишем пустой класс
    fclose(f);
    struct BinNotPack1 // неупакованная структура
    {    double a;  char ch; int b; };
    BinNotPack1 A = { 1.0, 'a', 1};
    cout << sizeof(A) << endl; // размер = 16
    if((f = fopen("c:/binfiles/binnotpack1.bin", "wb" )) == NULL) 
        return 1; // ошибка при открытии
    fwrite(&A, 1, sizeof(A), f);            // на диске - 16
    fclose(f);
    struct BinNotPack2 // неупакованная структура
    {    int b; double a; char ch;  };
    BinNotPack2 B = { 1, 1.0,'a'};
    cout << sizeof(B) << endl; // размер = 24
    if((f = fopen("c:/binfiles/binnotpack2.bin", "wb" )) == NULL) 
        return 1; // ошибка при открытии
    fwrite(&B, 1, sizeof(B), f); // на диске - 24
    fclose(f);
}
Эта простая программа записывает в наш каталог BinFiles три файла: binempty.bin, binnotpack1.bin и binnotpack2.bin. В первый файл записывается «пустой» класс, а во второй и третий – специально не выровненные структуры. Как выясняется, на диск записывается точно столько же байт, сколько структура занимает в памяти. В системе Visual C++.NET 2003 при отсутствии директивы выравнивания размеры переменных Empty t, BinNotPack1 A, BinNotPack2 B равны 1, 16 и 24 байта соответственно. Ровно столько же места они занимают и на диске — каждая в своем файле. Если же прописать директиву выравнивания
C++
1
#pragma pack(1)
, то размеры структур станут равны 13 — столько же и записывается в файлы.

В системе Borland C++ Builder 6 наблюдается аналогичная картина. При отсутствии выравнивания на диск записывается 8, 16 и 24 байта . При наличии директивы выравнивания на диск записывается столько же байт, как и в системе Visual C++ — 1,13 и 13 байт.

Нужно упомянуть об одной важной детали, связанной с двоичным вводом/выводом. Программа, которая считывает информацию из двоичного файла, должна «знать» размер и структуру считываемой информации. При записи в файл туда попадает только та информация, которая явно задана в операторах вывода. Никаких данных о типе выводимого значения на диске нет, если только мы сами их туда не запишем. Поэтому очень просто совершить ошибку: записать в файл число одного типа, а прочитать записанные байты в переменную другого типа. Например, int и float в системе Visual C++.NET 2003 занимают в памяти одинаковое количество байтов — четыре. Поэтому в приведенных выше примерах (листинг 10.12) можно было бы записать на диск массив дробных чисел типа float, а считывать его как массив целых чисел. Никаких сообщений об ошибках, естественно, не выдается; программа может даже работать, но результат, как вы понимаете, будет абсолютно неверным.
Поэтому функции ввода/вывода обычно разрабатываются «парами»: одна для записи в файл, другая — для чтения из файла.
3
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
inter-admin
Эксперт
29715 / 6470 / 2152
Регистрация: 06.03.2009
Сообщений: 28,500
Блог
16.10.2011, 22:19
Помогаю со студенческими работами здесь

Сохранение и загрузка из файла
Столкнулся с проблемой загрузки из файла *.ini. для сохранения параметров программы использую ...

Сохранение текстового файла
void __fastcall TForm2::N4Click(TObject *Sender) { dot *T; int n; dot *Q; int m; int i; FILE*f;

Memo, сохранение файла
У меня несколько кнопок, которые открывают определенный текстовый файл. Например кнопка A открывает a.txt , B -&gt; b и т.д. Как...

Сохранение txt-файла
Сохраняю файл прямиком в папку с проектом: Memo1-&gt;Lines-&gt;SaveToFile(ExtractFileDir(ParamStr(0))+&quot;\&quot;+&quot;.txt&quot;); Как...

Сохранение XML файла
Вывожу с xml файла данные в ListView, далее хочу сохранить эти данные в этом же виде только в новом текстовом или xml файле с помощью...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Новые блоги и статьи
Использование SDL3-callbacks вместо функции main() на Android, Desktop и WebAssembly
8Observer8 24.01.2026
Если вы откроете примеры для начинающих на официальном репозитории SDL3 в папке: examples, то вы увидите, что все примеры используют следующие четыре обязательные функции, а привычная функция main(). . .
моя боль
iceja 24.01.2026
Выложила интерполяцию кубическими сплайнами www. iceja. net REST сервисы временно не работают, только через Web. Написала за 56 рабочих часов этот сайт с нуля. При помощи perplexity. ai PRO , при. . .
Модель сукцессии микоризы
anaschu 24.01.2026
Решили писать научную статью с неким РОманом
http://iceja.net/ математические сервисы
iceja 20.01.2026
Обновила свой сайт http:/ / iceja. net/ , приделала Fast Fourier Transform экстраполяцию сигналов. Однако предсказывает далеко не каждый сигнал (см ограничения http:/ / iceja. net/ fourier/ docs ). Также. . .
http://iceja.net/ сервер решения полиномов
iceja 18.01.2026
Выкатила http:/ / iceja. net/ сервер решения полиномов (находит действительные корни полиномов методом Штурма). На сайте документация по API, но скажу прямо VPS слабенький и 200 000 полиномов. . .
Расчёт переходных процессов в цепи постоянного тока
igorrr37 16.01.2026
/ * Дана цепь(не выше 3-го порядка) постоянного тока с элементами R, L, C, k(ключ), U, E, J. Программа находит переходные токи и напряжения на элементах схемы классическим методом(1 и 2 з-ны. . .
Восстановить юзерскрипты Greasemonkey из бэкапа браузера
damix 15.01.2026
Если восстановить из бэкапа профиль Firefox после переустановки винды, то список юзерскриптов в Greasemonkey будет пустым. Но восстановить их можно так. Для этого понадобится консольная утилита. . .
Сукцессия микоризы: основная теория в виде двух уравнений.
anaschu 11.01.2026
https:/ / rutube. ru/ video/ 7a537f578d808e67a3c6fd818a44a5c4/
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2026, CyberForum.ru