Запись с использованием ‹‹ в fstream

Я пытаюсь написать long в текстовый файл, используя класс С++ fstream. Файл уже создан на диске перед выполнением. Я запускаю следующий код и могу прочитать начальное значение, но не могу сохранить новое, перезаписывая его. Что я делаю не так?

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>


using namespace std;

int main(int argc, char* argv[]) {

    long f;

    fstream myFile("data.txt", fstream::in|fstream::out);
    cout << "f before: " << f << endl;
    myFile >> f;
    cout << "f after: " << f << endl;
    f++;
    cout << "f after increment: " << f << endl;

    myFile << f;
    myFile.close();

    return 0;
}

После этого я прочитал значение в файле, и оно не изменилось. Что я здесь сделал не так?


person Thiago Moraes    schedule 14.12.2012    source источник
comment
сначала инициализируйте 'f' до 0. вы пишете новое f после старого, а не на том же месте.   -  person AndersK    schedule 14.12.2012


Ответы (4)


Вам нужно добавить myFile.seekp(ios::beg); непосредственно перед myFile << f;, чтобы правильно обновить счетчик.

Если вы хотите продолжить добавление в конец, добавьте myFile.clear(); перед myFile << f;. Это приведет к тому, что содержимое станет следующим: 1->12->1213->12131214->1213121412131215. Это необходимо, потому что eof достигается при чтении ввода. Обратите внимание, что указатели get и put являются одинаковыми.

Как вы правильно заметили, это необходимо, потому что файл имеет только номер, даже не новую строку. Таким образом, операция чтения попадает прямо в EOF и вызывает проблемы. Чтобы обойти это, мы очищаем eof status и продолжаем.

Добавление новой строки в конце - это решение, как вы предложили. В таком случае

myFile.seekp(ios::beg);
myFile << f<<"\n";

Было бы полное решение.

person axiom    schedule 14.12.2012
comment
Просто повторяю комментарий сверху: если это так, не следует ли записывать новый контент в конец файла? Если нет, то почему? - person Thiago Moraes; 14.12.2012
comment
@ThiagoMoraes Обновлено, посмотрите. - person axiom; 14.12.2012
comment
Ну, ты ответил, а я не видел. Мой прокси не позволяет мне помечать ответы как правильные, поэтому прошу прощения или что-то в этом роде. Благодарю вас! - person Thiago Moraes; 14.12.2012

Перед записью необходимо перемотать файл на начало. В противном случае второе значение записывается после первого.

person NPE    schedule 14.12.2012
comment
Если это так, не следует ли записывать новое содержимое в конец файла? Если нет, то почему? - person Thiago Moraes; 14.12.2012
comment
@ThiagoMoraes: Если предположить, что число — это единственное, что содержится в файле, да. На самом деле, когда я запускаю ваш код, происходит именно это. - person NPE; 14.12.2012
comment
В моих системах это происходит только для 2 прогонов. После этого обновления файла нет. Чтобы он работал всегда, нам нужно очистить статус ошибки. Обновил мой ответ. - person axiom; 14.12.2012
comment
К сожалению, здесь этого не происходит. Когда я закрываю и снова открываю файл, как сказано в ответе Кевина, он работает, но я не понимаю, требуется ли это. - person Thiago Moraes; 14.12.2012

Я понял, что я делаю неправильно здесь:

В моем файле было ТОЛЬКО то длинное, что я хотел потом прочитать и записать. Когда я прочитал файл, я дошел до EOF, после чего не смог ни перемотать, ни написать что-либо в конце.

Тем не менее, мое решение состояло в том, чтобы включить пробел или \n в конце файла.

Кто-нибудь знает, почему API работает таким образом? Мне кажется не очень полезно...

person Thiago Moraes    schedule 14.12.2012
comment
оператор ›› читает до новой строки. Если он читает что-то, что не может понять, устанавливается бит ошибки. именно по этой причине вам нужно было вызвать clear() перед записью. Кроме того, вы можете отредактировать свой вопрос, чтобы включить это. - person axiom; 14.12.2012

Это связано с этой строкой:

мой файл >> ф;

Удалите его, и все будет работать нормально. Я не знаком с fstream, но мне кажется, что этот код попытается заставить строку быть длинной. Мне также не разрешено приводить его к длинному значению, что заставляет меня думать, что это никогда не должно выполняться таким образом. Я предлагаю вам прочитать о том, как получить значение из файла в виде длинного типа, а затем повторить попытку.

редактировать:
Немного прочитав это сайт предложил вам закрыть и снова открыть файл между чтением и записью, я был поражен, что это действительно было исправлено. Я не могу не задаться вопросом, почему, хотя я думал, что fstream предназначен для чтения ИЛИ записи ИЛИ того и другого .... Во всяком случае, вот ваш рабочий код:

#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <fstream>

using namespace std;

int main(int argc, char* argv[]) {

    long f;

    fstream myFile("data.txt", fstream::in|fstream::out);
    cout << "f before: " << f << endl;
    myFile >> f;
    cout << "f after: " << f << endl;
    f++;
    cout << "f after increment: " << f << endl;
    myFile.close();
    myFile.open("data.txt", fstream::in|fstream::out);

    myFile << f;
    myFile.close();

    return 0;
}
person Kevin    schedule 14.12.2012
comment
-1: с линией все в порядке; это именно то, как вы должны получить long из (отформатированного) потока. - person Angew is no longer proud of SO; 14.12.2012
comment
Как я уже сказал, я не знаком с fstream, но я могу писать в файл, если я удаляю эту строку, и я не могу писать в файл, когда я оставляю эту строку. Не знаю, почему меня минусуют, потому что я не сказал ничего, что было бы неправдой. - person Kevin; 14.12.2012
comment
Ну, вы сказали, что мне кажется, что этот код попытается заставить строку быть длинной, и это никогда не должно выполняться таким образом. Я предлагаю вам прочитать о том, как получить значение из файла в виде длинного типа. Это делает ваш (исходный) ответ вводящим в заблуждение, поскольку myFile >> f; является правильным способом извлечения значения из файла в виде длинного типа. - person Angew is no longer proud of SO; 14.12.2012
comment
Вроде как открытие файла снова работает. Это не идеальное решение для моего реального случая, но решает эту конкретную проблему. - person Thiago Moraes; 14.12.2012