Многократное чередование чтения и письма

Моя цель - прочитать файл построчно, проверить, содержит ли эта строка какое-то число, и если да, то переписать эту строку. Затем продолжите чтение файла. Мне удалось сделать это для одной строки, но я не могу понять, как продолжить чтение остальной части файла. Вот как я заменяю одну строку (каждая строка имеет известный фиксированный размер):

while(getline(fs, line)){
  if(condition){
    pos = fs.tellg();       //gets current read position (end of the line I want to change)
    pos -= line.length()+1;    //position of the beginning of the line
    fs.clear();             //switch to write mode
    fs.seekp(pos);          //seek to beginning of line
    fs << new_data;         //overwrite old data with new data (also fixed size)
    fs.close();             //Done.
    continue;
  }
}

Как вернуться к чтению и продолжить цикл getline?


person George    schedule 20.03.2016    source источник
comment
Чтобы исправить это, потребуется больше символов, чем я готов написать прямо сейчас. Ваш подход совершенно неверен. fs.close() явно неверен, но есть более фундаментальная проблема, заключающаяся в том, что вы не можете просто заменить строки на месте, как здесь. И я не знаю, где вы слышали, что fs.clear() переключается в режим записи; это наверняка не так.   -  person Lightness Races in Orbit    schedule 20.03.2016
comment
закрытие в цикле while предотвратит дальнейшее чтение. Замените закрытие на заподлицо. Кроме того, продолжение в конце блока излишне, закомментируйте его и посмотрите, есть ли разница в поведении.   -  person Arif Burhan    schedule 20.03.2016
comment
Вы хотите в основном grep -w number a > b ; mv b a   -  person Breaking not so bad    schedule 20.03.2016
comment
Кроме того, если файл не заканчивается символом новой строки, line.length()+1 будет неправильным, и это приведет к затиранию символа новой строки перед последней строкой. И если файл непустой, но вообще не имеет символов новой строки, это будет поведение undefined. Это также, по-видимому, будет ошибаться в технически несовершенных операционных системах, которые используют многобайтовую последовательность для представления логического перехода на новую строку — мне скучно, я хотел бы начать флейм-войну, поехали!   -  person Sam Varshavchik    schedule 20.03.2016
comment
@Barry: Код, который я разместил, предназначен для перезаписи одной строки. Я пытаюсь изменить его, чтобы перезаписать несколько строк.   -  person George    schedule 20.03.2016
comment
@Sam: когда я вставляю данные в этот файл, к ним добавляется endl, поэтому после каждой строки обязательно будет новая строка. Хотя я открыт для любых предложений.   -  person George    schedule 20.03.2016
comment
@ringø да, точно, но без перезаписи/замены всего файла.   -  person George    schedule 20.03.2016
comment
Если ВСЕ ваши записи в файле не имеют абсолютно одинаковой длины и одного и того же числа до/после, вы не можете надежно перезаписать в файл, из которого вы читаете (по крайней мере, не со стандартными функциями C или C++). Используйте два файла. Так делает все здравомыслящее.   -  person Mats Petersson    schedule 20.03.2016
comment
@Mats все записи имеют одинаковую длину. Новые данные будут дополнены пробелами до фиксированного размера. Все, что превышает фиксированный размер, будет отклонено. Или дополняется нулями, если запись представляет собой число.   -  person George    schedule 20.03.2016


Ответы (1)


У меня была та же проблема, файлы масштаба ТБ, и я хотел изменить некоторую информацию заголовка в начале файла. Очевидно, что при первоначальном создании файла необходимо оставить достаточно места для любого нового содержимого, потому что нет способа увеличить размер файла (кроме добавления к нему), а новая строка должна иметь точно такую ​​же длину строки, что и исходная. .

Вот упрощение моего кода:

#include <iostream>
#include <fstream>
using namespace std;

bool CreateDummy()
{
  ofstream out;
  out.open("Dummy.txt");
  // skip: test if open

  out<<"Some Header"<<endl;
  out<<"REPLACE1  12345678901234567890"<<endl;
  out<<"REPLACE2  12345678901234567890"<<endl;
  out<<"Now ~1 TB of data follows..."<<endl;

  out.close();

  return true;
}


int main()
{
  CreateDummy(); // skip: test if successful

  fstream inout;
  inout.open("Dummy.txt", ios::in | ios::out);
  // skip test if open

  bool FoundFirst = false;
  string FirstText = "REPLACE1";
  string FirstReplacement = "Replaced first!!!";

  bool FoundSecond = false;
  string SecondText = "REPLACE2";
  string SecondReplacement = "Replaced second!!!";

  string Line;
  size_t LastPos = inout.tellg();
  while (getline(inout, Line)) {
    if (FoundFirst == false && Line.compare(0, FirstText.size(), FirstText) == 0) {
      // skip: check if Line.size() >= FirstReplacement.size()
      while (FirstReplacement.size() < Line.size()) FirstReplacement += " ";
      FirstReplacement += '\n';

      inout.seekp(LastPos);
      inout.write(FirstReplacement.c_str(), FirstReplacement.size());
      FoundFirst = true;
    } else if (FoundSecond == false && Line.compare(0, SecondText.size(), SecondText) == 0) {
      // skip: check if Line.size() >= SecondReplacement.size()
      while (SecondReplacement.size() < Line.size()) SecondReplacement += " ";
      SecondReplacement += '\n';

      inout.seekp(LastPos);
      inout.write(SecondReplacement.c_str(), SecondReplacement.size());
      FoundSecond = true;
    }

    if (FoundFirst == true && FoundSecond == true) break;
    LastPos = inout.tellg();
  }
  inout.close();

  return 0;
}

Вход

Some Header
REPLACE1  12345678901234567890             
REPLACE2  12345678901234567890             
Now ~1 TB of data follows...

Результат:

Some Header
Replaced first!!!             
Replaced second!!!            
Now ~1 TB of data follows...
person ExplodingStar    schedule 20.03.2016