Перезаписать только определенную часть файла - PullRequest
2 голосов
/ 30 марта 2011

Я знаю, что это было один раз спросили , но я не понял ответа.

Допустим, у меня есть файл, подобный этому:

Guest list:
jon
mary
paul
luke
Table list:

Итогда, например, я хочу изменить имена гостей.Я понял, что мне нужно найти строку «Список гостей», а затем перезаписать все между «Список гостей» и «Список таблиц».Но я понятия не имею, как это сделать.

Я использую C ++, и я предпочитаю использовать fstream: D

Спасибо!

edit:

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

Ответы [ 3 ]

3 голосов
/ 30 марта 2011

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

  • ПрочитайтеОригинальный файл построчно, пока вы не найдете разделитель «Список гостей:», копируя каждую строку во временный файл.
  • Запишите новый список гостей во временный файл.
  • Читайте строки из исходного файла, пока не найдете разделитель «Список таблиц:».
  • Считайте строку исходного файладо конца строки, копируя каждую строку во временный файл.
  • Удалить оригинальный файл.(Или переименуйте его, добавив к его имени расширение резервной копии.)
  • Переименуйте временный файл в имя исходного файла.
0 голосов
/ 30 марта 2011

Итак, вот некоторый код (такого рода проблемы не так просты, как кажется на первый взгляд):

#include <iostream>
#include <fstream>
#include <list>
#include <string>
#include <iterator>
#include <algorithm>

int main()
{
    std::list<std::string> data;

    // load data from file line-by-line
    { // you can make this a function if you want
        std::ifstream file("test.txt");
        std::string buffer;
        while(std::getline(file, buffer))
            data.push_back(buffer);
    } // end of scope - file gets closed for us

    // find end of guest-list - this is where new guests are added
    std::list<std::string>::iterator guest_list_end = 
        std::find(data.begin(), data.end(), "Table list:");

    data.remove("mary"); // remove mary from guest-list
    data.insert(guest_list_end, "betty"); // append betty to guest-list
    data.insert(guest_list_end, "harry"); // append harry to guest-list

    // write entire file back
    std::ofstream file("test.txt");
    std::copy(data.begin(), data.end(), 
        std::ostream_iterator<std::string>(file, "\n"));
}

Поскольку в этом примере используется std::list, итератор guest_list_end остается в силе, даже когда мы добавляем или удаляем гостей.Имейте в виду, что find и remove в списках имеют линейную сложность, поэтому, если файл длинный, это может быть дорого.

В этом коде также предполагается, что за гостем следует список таблиц.Если это изменится, вы должны изменить find -статмент.

0 голосов
/ 30 марта 2011

Если вы можете разместить весь файл в памяти (как указывал Space), прочитайте его, используя ifstream, и, используя ofstream, запишите строку "Список гостей" и все новые имена. Это не единственный способ, но самый удобный.

...