C ++: метод std :: ofstream open () стирает открытый файл ifstream на второй итерации - PullRequest
0 голосов
/ 22 сентября 2018

Я пытаюсь создать «fileUpdater», который будет копировать оригинальный файл в несколько каталогов, где ранее был найден файл с тем же именем и расширением.

bool update_files(const string inputPath, const vector<string> outputPaths)
{
    ifstream src(inputPath);
    if(!src.is_open())
    {
        cout << "Unable to open input file\n" << inputPath <<endl;
        return false;
    }
    else
    {
        ofstream dst;
        for(unsigned int i=0; i<= outputPaths.size()-1; i++)
        {
            dst.open(outputPaths[i]);
            try
            {
                dst << src.rdbuf();
                dst.close();
            }
            catch(int e)
            {
                cout << "Unable to replace file\n" <<endl;
                cout << outputPaths[i] <<"\n"<< endl;
                cout << "Error code: " <<e<<endl;
            }
        }
    };
    src.close();
    return true;
}

Точно после выполнения

dst.open(outputPaths[i]);

во второй итерации, исходный файл, открытый

ifstream src(inputPath);

, стирается, и в оставшиеся каталоги копируется только пустой файл.Я также пытался

dst.clear();
dst.close();

и

src.clear();
src.seekg(0,ios::beg);

перед входом в следующую итерацию, но это не имело никакого значения.

ОБНОВЛЕНИЕ После попытки другогофайлы, я понял, поведение зависит от входного файла.Вышеупомянутое поведение появилось для .m-файлов (MatLab).После тестирования с файлами .txt все файлы были стерты.

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

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

До сих пор неясно почемуdst.open(outputPaths[i]); стирает входной файл.Также точный момент стирания зависит от используемых типов файлов.

Я реализовал следующий обходной путь, эффективно считывая входной файл в строку и предварительно закрывая его, чтобы защитить его от дальнейших действий чтения / записи.

bool update_files( const string inputPath, const vector<string> outputPaths)
{
    const char * in = inputPath.c_str();
    ifstream src(in);
    if(!src.is_open())
    {
        cout << "Unable to open input file\n" << inputPath <<endl;
        return false;
    }
    else
    {
        string buffer;
        streamsize s=src.gcount();
        src.seekg(0,ios::end);
        buffer.reserve(src.tellg());
        src.seekg(0,ios::beg);
        buffer.assign((istreambuf_iterator<char>(src)), istreambuf_iterator<char>());
        src.close();

        for(unsigned int i=0; i<= outputPaths.size()-1; i++)
        {
            const char * out = outputPaths[i].c_str();
            ofstream dst(out);
            try
            {
                dst << buffer;
                dst.close();
            }
            catch(int e)
            {
                cout << "Unable to replace file\n" <<endl;
                cout << outputPaths[i] <<"\n"<< endl;
                cout << "Error code: " <<e<<endl;
            }
        }
    };
    src.close();
    return true;
}
0 голосов
/ 22 сентября 2018

То, как вы копируете файл с помощью dst << src.rdbuf();, оставит текущую позицию файла в конце вашего входного файла.На второй итерации то же самое чтение ничего не прочитает (оставляя пустую копию файла), потому что вы уже в конце входного файла.

Решение состоит в том, чтобы вернуться к началувходного файла перед каждым чтением, используя seekg.Вы должны позвонить tellg перед чтением чего-либо (сразу после открытия файла), а затем искать эту позицию.

auto startpos = src.tellg();
ofstream dst;
// ...
src.seekg(startpos);
dst << src.rdbuf();
...