Перейти к содержимому

Как перезаписывать файл c

  • автор:

Как перезаписывать файл 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

Файловая система 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 комментария

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *

Luxury Car Rental in Miami | Reserve a Premium Vehicle with RealCar