Как перезаписывать файл c
Потоки для работы с текстовыми файлами представляют объекты, для которых не задан режим открытия ios::binary .
Запись в файл
Для записи в файл к объекту ofstream или fstream применяется оператор
#include #include int main() < std::ofstream out; // поток для записи out.open("hello.txt"); // открываем файл для записи if (out.is_open()) < out out.close(); std::cout
Здесь предполагается, что файла «hello.txt» располагается в одной папке с файлом программы. Данный способ перезаписывает файл заново. Если надо дозаписать текст в конец файла, то для открытия файла нужно использовать режим ios::app :
std::ofstream out("hello.txt", std::ios::app); if (out.is_open()) < out out.close();
Чтение из файла
Если надо считать всю строку целиком или даже все строки из файла, то лучше использовать встроенную функцию getline() , которая принимает поток для чтения и переменную, в которую надо считать текст:
#include #include #include // для std::getline int main() < std::string line; std::ifstream in("hello.txt"); // окрываем файл для чтения if (in.is_open()) < while (std::getline(in, line)) < std::cout > in.close(); // закрываем файл >
Также для чтения данных из файла для объектов ifstream и fstream может применяться оператор >> (также как и при чтении с консоли):
#include #include #include struct Point < Point(double x, double y): x, y <> double x; double y; >; int main() < std::vectorpoints< Point, Point, Point>; std::ofstream out("points.txt"); if (out.is_open()) < // записываем все объекты Point в файл for (const Point& point: points) < out > out.close(); std::vector new_points; std::ifstream in("points.txt"); // окрываем файл для чтения if (in.is_open()) < double x, y; while (in >> x >> y) < new_points.push_back(Point); > > in.close(); for (const Point& point: new_points) < std::cout >
Здесь вектор структур Point записывается в файл.
for (const Point& point: points)
При чем при записи значений переменных файл они отделяются пробелом. В итоге будет создаваться файл в формате
0 0 4 5 -5 7
Используя оператор >>, можно считать последовательно данные в переменные x и y и ими инициализировать структуру.
double x, y; while (in >> x >> y) < new_points.push_back(Point); >
Но стоит отметить, что это ограниченный способ, поскольку при чтении файла поток in использует пробел для отделения одного значения от другого и таким образом считывает эти значения в переменные x и y. Если же нам надо записать и затем считать строку, которая содержит пробелы, и какие-то другие данные, то такой способ, конечно, не сработает.
Как перезаписывать файл c
Нужно открывать фаил в fstream, копировать его содержимое в строку string, работать с ней как с буфером, а при условии, что она изменена, перезаписывать файл её содержимым.
Т.е. так. Открываем:
char *fn; string *buf; fstream *fS; fS->open(fname, ios_base::in | ios_base::out); if(!fS->is_open()) < fS->open(fname, ios_base::in | ios_base::out | ios_base::trunc); if(!fS->is_open()) return 1; > this->defSize(); char *tstr = new char[this->size]; this->buf = new string(); fS->read(tstr, this->size); this->buf->insert(0, tstr);
А затем надо сохранить содержимое buf в файл fS.
Сначала необходимо удалить предыдущее содержимое. Пробовал двумя способами.
Первый:
this->fS->clear();
this->fS->close(); this->fS->open(this->fn, ios_base::in | ios_base::out | ios_base::trunc);
После чего запись:
fS->seekg(0, ios_base::beg); char *tstr = new char[this->size]; strcpy(tstr, buf->data()); this->fS->write(tstr, size);
В первом случае, если содержимое буфера уменьшилось, то на конце файла будут символы 'H'.
Во втором — на выходе оказывается пустой файл.
Как правильно перезаписать файл fstream?
Re: Перезаписать fstream
| От: | LaptevVV |
| Дата: | 12.09.08 11:09 |
| Оценка: |
Здравствуйте, NordWest, Вы писали:
NW>Нужно открывать фаил в fstream, копировать его содержимое в строку string, работать с ней как с буфером, а при условии, что она изменена, перезаписывать файл её содержимым.
NW>Т.е. так. Открываем:
NW>
NW> char *fn; NW> string *buf; NW> fstream *fS; fS->>open(fname, ios_base::in | ios_base::out); NW> if(!fS->is_open()) NW> < fS->>open(fname, ios_base::in | ios_base::out | ios_base::trunc); NW> if(!fS->is_open()) return 1; NW> > this->>defSize(); NW> char *tstr = new char[this->size]; this->>buf = new string(); fS->>read(tstr, this->size); this->>buf->insert(0, tstr); NW>
Вопросы:
1. Зачем тотальное использование указателей? Почему нельзя объявить просто указатель на поток, а не указатель на него? Аналогично: почему указатель на строку, а не просто строка?
2. Файл по умолчанию текстовый. Читаешь ты его методом read — в символьный массив. А внутри символы '\n' отсутствуют? А ноль на конце символьного массива есть? При вставке проблем не будет?
NW>А затем надо сохранить содержимое buf в файл fS.
NW>Сначала необходимо удалить предыдущее содержимое. Пробовал двумя способами.
NW>Первый:
NW>
this->>fS->clear(); NW>
Это неверно. Метод clear очищает флаги, а не файл.
NW>Второй:
NW>
this->>fS->close(); this->>fS->open(this->fn, ios_base::in | ios_base::out | ios_base::trunc); NW>
Гораздо проще записать в новый временный файл, а потом просто переименовать.
Хочешь быть счастливым — будь им!
Без булдырабыз.
Re: Перезаписать fstream
| От: | codelord | |
| Дата: | 15.09.08 08:40 | |
| Оценка: | 3 (1) | |
Здравствуйте, NordWest, Вы писали:
NW>Нужно открывать фаил в fstream, копировать его содержимое в строку string, работать с ней как с буфером, а при условии, что она изменена, перезаписывать файл её содержимым.
Может конечно очень многословно, но вот например так:
#include #include size_t get_file_size( const char * filename ) < FILE *fp = fopen( filename, "rb" ); if ( !fp ) < return 0; > size_t res; fpos_t position; if ( fgetpos(fp, &position) ) //запоминаем текущую позицию < fclose(fp); return -1; > //ошибка получения текущей позиции файла fseek(fp, 0, SEEK_END); //смещаемся в конец файла res = ftell(fp); //читаем положение указателя в конце файла if ( fsetpos(fp, &position) ) //кладем откуда взяли (позицию файла) < fclose(fp); return -1; > //ошибка установки позиции файла fclose(fp); return res; > void file_to_buf( char *buf, size_t _len, std::string filename ) < std::ifstream infile( filename.c_str(), std::ios::binary ); if ( !infile ) < return; > infile.read( buf, _len ); infile.close(); > int main() < std::string filename = "infile.txt"; size_t fsize = get_file_size( filename.c_str() ); char *buf = new char[ fsize ]; file_to_buf( buf, fsize, filename ); //Работаем с буфером buf[0] = 'A'; //можем копировать буфер чтобы сравнивать до и после изменений //и в случае если изменилось перезаписать файл std::ofstream outfile( filename.c_str() ); outfile.write( buf, fsize ); >
Re[2]: Перезаписать fstream
| От: | codelord |
| Дата: | 15.09.08 08:43 |
| Оценка: |
Здравствуйте, codelord, Вы писали:
C>Может конечно очень многословно, но вот например так:
Ой там в последнюю строчку надо
delete [] buf;
Re[2]: Перезаписать fstream
| От: | NordWest |
| Дата: | 15.09.08 15:47 |
| Оценка: |
Здравствуйте, codelord, Вы писали:
C> std::ofstream outfile( filename.c_str() );
C> outfile.write( buf, fsize );
fsize может поменяться.
Re[3]: Перезаписать fstream
| От: | codelord |
| Дата: | 16.09.08 05:14 |
| Оценка: |
Здравствуйте, NordWest, Вы писали:
NW>Здравствуйте, codelord, Вы писали:
C>> std::ofstream outfile( filename.c_str() );
C>> outfile.write( buf, fsize );
NW>fsize может поменяться.
Ну так это же пример, меняйте
Re[4]: Перезаписать fstream
| От: | NordWest |
| Дата: | 16.09.08 06:11 |
| Оценка: |
Здравствуйте, codelord, Вы писали:
C>Здравствуйте, NordWest, Вы писали:
NW>>Здравствуйте, codelord, Вы писали:
C>>> std::ofstream outfile( filename.c_str() );
C>>> outfile.write( buf, fsize );
NW>>fsize может поменяться.
C>Ну так это же пример, меняйте
Re[5]: Перезаписать fstream
| От: | Аноним |
| Дата: | 16.09.08 11:51 |
| Оценка: |
Работа с файлами
Для удобства обращения информация в запоминающих устройствах хранится в виде файлов.
Файл – именованная область внешней памяти, выделенная для хранения массива данных. Данные, содержащиеся в файлах, имеют самый разнообразный характер: программы на алгоритмическом или машинном языке; исходные данные для работы программ или результаты выполнения программ; произвольные тексты; графические изображения и т. п.
Каталог ( папка , директория ) – именованная совокупность байтов на носителе информации, содержащая название подкаталогов и файлов, используется в файловой системе для упрощения организации файлов.
Файловой системой называется функциональная часть операционной системы, обеспечивающая выполнение операций над файлами. Примерами файловых систем являются FAT (FAT – File Allocation Table, таблица размещения файлов), NTFS, UDF (используется на компакт-дисках).
Существуют три основные версии FAT: FAT12, FAT16 и FAT32. Они отличаются разрядностью записей в дисковой структуре, т.е. количеством бит, отведённых для хранения номера кластера. FAT12 применяется в основном для дискет (до 4 кбайт), FAT16 – для дисков малого объёма, FAT32 – для FLASH-накопителей большой емкости (до 32 Гбайт).
Рассмотрим структуру файловой системы на примере FAT32.
Файловая структура FAT32
Устройства внешней памяти в системе FAT32 имеют не байтовую, а блочную адресацию. Запись информации в устройство внешней памяти осуществляется блоками или секторами.
Сектор – минимальная адресуемая единица хранения информации на внешних запоминающих устройствах. Как правило, размер сектора фиксирован и составляет 512 байт. Для увеличения адресного пространства устройств внешней памяти сектора объединяют в группы, называемые кластерами.
Кластер – объединение нескольких секторов, которое может рассматриваться как самостоятельная единица, обладающая определёнными свойствами. Основным свойством кластера является его размер, измеряемый в количестве секторов или количестве байт.

Файловая система FAT32 имеет следующую структуру.
Нумерация кластеров, используемых для записи файлов, ведется с 2. Как правило, кластер №2 используется корневым каталогом, а начиная с кластера №3 хранится массив данных. Сектора, используемые для хранения информации, представленной выше корневого каталога, в кластеры не объединяются.
Минимальный размер файла, занимаемый на диске, соответствует 1 кластеру.
Загрузочный сектор начинается следующей информацией:
- EB 58 90 – безусловный переход и сигнатура;
- 4D 53 44 4F 53 35 2E 30 MSDOS5.0;
- 00 02 – количество байт в секторе (обычно 512);
- 1 байт – количество секторов в кластере;
- 2 байта – количество резервных секторов.
Кроме того, загрузочный сектор содержит следующую важную информацию:
- 0x10 (1 байт) – количество таблиц FAT (обычно 2);
- 0x20 (4 байта) – количество секторов на диске;
- 0x2С (4 байта) – номер кластера корневого каталога;
- 0x47 (11 байт) – метка тома;
- 0x1FE (2 байта) – сигнатура загрузочного сектора ( 55 AA ).
Сектор информации файловой системы содержит:
- 0x00 (4 байта) – сигнатура ( 52 52 61 41 );
- 0x1E4 (4 байта) – сигнатура ( 72 72 41 61 );
- 0x1E8 (4 байта) – количество свободных кластеров, -1 если не известно;
- 0x1EС (4 байта) – номер последнего записанного кластера;
- 0x1FE (2 байта) – сигнатура ( 55 AA ).
Таблица FAT содержит информацию о состоянии каждого кластера на диске. Младшие 2 байт таблицы FAT хранят F8 FF FF 0F FF FF FF FF (что соответствует состоянию кластеров 0 и 1, физически отсутствующих). Далее состояние каждого кластера содержит номер кластера, в котором продолжается текущий файл или следующую информацию:
- 00 00 00 00 – кластер свободен;
- FF FF FF 0F – конец текущего файла.
Корневой каталог содержит набор 32-битных записей информации о каждом файле, содержащих следующую информацию:
- 8 байт – имя файла;
- 3 байта – расширение файла;
Корневой каталог содержит набор 32-битных записей информации о каждом файле, содержащих следующую информацию:
- 8 байт – имя файла;
- 3 байта – расширение файла;
- 1 байт – атрибут файла:

- 1 байт – зарезервирован;
- 1 байт – время создания (миллисекунды) (число от 0 до 199);
- 2 байта – время создания (с точностью до 2с):

- 2 байта – дата создания:

- 2 байта – дата последнего доступа;
- 2 байта – старшие 2 байта начального кластера;
- 2 байта – время последней модификации;
- 2 байта – дата последней модификации;
- 2 байта – младшие 2 байта начального кластера;
- 4 байта – размер файла (в байтах).
В случае работы с длинными именами файлов (включая русские имена) кодировка имени файла производится в системе кодировки UTF-16. При этого для кодирования каждого символа отводится 2 байта. При этом имя файла записывается в виде следующей структуры:
- 1 байт последовательности;
- 10 байт содержат младшие 5 символов имени файла;
- 1 байт атрибут;
- 1 байт резервный;
- 1 байт – контрольная сумма имени DOS;
- 12 байт содержат младшие 3 символа имени файла;
- 2 байта – номер первого кластера;
- остальные символы длинного имени.
Далее следует запись, включающая имя файла в формате 8.3 в обычном формате.
Работа с файлами в языке Си
Для программиста открытый файл представляется как последовательность считываемых или записываемых данных. При открытии файла с ним связывается поток ввода-вывода . Выводимая информация записывается в поток, вводимая информация считывается из потока.
Когда поток открывается для ввода-вывода, он связывается со стандартной структурой типа FILE , которая определена в stdio.h . Структура FILE содержит необходимую информацию о файле.
Открытие файла осуществляется с помощью функции fopen() , которая возвращает указатель на структуру типа FILE , который можно использовать для последующих операций с файлом.
FILE *fopen(name, type);
name – имя открываемого файла (включая путь),
type — указатель на строку символов, определяющих способ доступа к файлу:
- "r" — открыть файл для чтения (файл должен существовать);
- "w" — открыть пустой файл для записи; если файл существует, то его содержимое теряется;
- "a" — открыть файл для записи в конец (для добавления); файл создается, если он не существует;
- "r+" — открыть файл для чтения и записи (файл должен существовать);
- "w+" — открыть пустой файл для чтения и записи; если файл существует, то его содержимое теряется;
- "a+" — открыть файл для чтения и дополнения, если файл не существует, то он создаётся.
Возвращаемое значение — указатель на открытый поток. Если обнаружена ошибка, то возвращается значение NULL .
Функция fclose() закрывает поток или потоки, связанные с открытыми при помощи функции fopen() файлами. Закрываемый поток определяется аргументом функции fclose() .
Возвращаемое значение: значение 0, если поток успешно закрыт; константа EOF , если произошла ошибка.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
#include
int main() FILE *fp;
char name[] = "my.txt" ;
if ((fp = fopen(name, "r" )) == NULL )
printf( "Не удалось открыть файл" );
getchar();
return 0;
>
// открыть файл удалось
. // требуемые действия над данными
fclose(fp);
getchar();
return 0;
>
Чтение символа из файла:
char fgetc(поток);
Аргументом функции является указатель на поток типа FILE . Функция возвращает код считанного символа. Если достигнут конец файла или возникла ошибка, возвращается константа EOF .
Запись символа в файл:
fputc(символ,поток);
Аргументами функции являются символ и указатель на поток типа FILE . Функция возвращает код считанного символа.
Функции fscanf() и fprintf() аналогичны функциям scanf() и printf() , но работают с файлами данных, и имеют первый аргумент — указатель на файл.
fscanf(поток, "ФорматВвода" , аргументы);
fprintf(поток, "ФорматВывода" , аргументы);
Функции fgets() и fputs() предназначены для ввода-вывода строк, они являются аналогами функций gets() и puts() для работы с файлами.
fgets(УказательНаСтроку, КоличествоСимволов, поток);
Символы читаются из потока до тех пор, пока не будет прочитан символ новой строки ‘\n’ , который включается в строку, или пока не наступит конец потока EOF или не будет прочитано максимальное количество символов. Результат помещается в указатель на строку и заканчивается нуль- символом ‘\0’ . Функция возвращает адрес строки.
fputs(УказательНаСтроку,поток);
Копирует строку в поток с текущей позиции. Завершающий нуль- символ не копируется.
Пример Ввести число и сохранить его в файле s1.txt. Считать число из файла s1.txt, увеличить его на 3 и сохранить в файле s2.txt.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#include
#include
int main()
FILE *S1, *S2;
int x, y;
system( "chcp 1251" );
system( "cls" );
printf( "Введите число : " );
scanf( "%d" , &x);
S1 = fopen( "S1.txt", "w" );
fprintf(S1, "%d" , x);
fclose(S1);
S1 = fopen( "S1.txt", "r" );
S2 = fopen( "S2.txt", "w" );
fscanf(S1, "%d" , &y);
y += 3;
fclose(S1);
fprintf(S2, "%d\n" , y);
fclose(S2);
return 0;
>

Результат выполнения — 2 файла
Работа с файлами в C++ описана здесь.
Комментариев к записи: 98
Как перезаписать текстовый файл в Qt C++?
Всем доброго времени суток. Нужен совет. Есть текстовый файл, нужно удалить из него строку. На просторах рунета прочитал, что такое можно реализовать с помощью перезаписи, но как именно это сделать я не нашёл. Отмечу, что размер файла может быть больше размера ОЗУ.
Моя версия: Создаю второй файл. И с помощью условия записываю в него строки, которые удалять не нужно. Правильно ли это? Или есть способ всё реализовать с одним файлом? Хотелось бы услышать и другие способы, помимо перезаписи. Спасибо.
- Вопрос задан более трёх лет назад
- 277 просмотров
3 комментария
Простой 3 комментария