Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > C/C++: Общие вопросы > Как вставить предпоследню строку файлового потока?


Автор: ТарасАтавин 18.9.2013, 08:46
Есть переменная 
Код
std::wofstream Log;
, с помощью которой в разных функциях происходит вывод в файл Log.xml В функции main происходит сброс лога: 
Код
Log.open("Log.xml");
Log<<"<?xml version=\"1.0\" encoding=\"windows-1251\"?>"<<std::endl;
Log<<"<root>"<<std::endl;
Log<<"</root>"<<std::endl;
, в остальных надо писать лог. Если просто аппендить 
Код
Log.open("Log.xml", std::ios::app);
Log<<"<Pos>"<<Pos<<"</Pos>";
Log.close();
, то получится, что текст добавляется в конец, а надо добавлять его перед строкой 
Код
</root>
. Заменить 
Код
Log<<"<Pos>"<<Pos<<"</Pos>"<<std::endl;
Log.close();
 на 
Код
Log<<"<Pos>"<<Pos<<"</Pos>"<<std::endl;
Log.close();
Log<<"<Pos>"<<Pos<<"</Pos>"
 не проблема, но если 
Код
Log.open("Log.xml", std::ios::app);
Log<<"<Pos>"<<Pos<<"</Pos>"<<std::endl;
Log.close();
 на 
Код
Log<<"<Pos>"<<Pos<<"</Pos>"<<std::endl;
Log.close();
Log<<"<Pos>"<<Pos<<"</Pos>"
, то получится 
Код
<?xml version="1.0" encoding="windows-1251"?>
<root>
</root><Pos>0</Pos>
</root><Pos>32</Pos>
</root><Pos>33</Pos>
</root>
, а надо 
Код
<?xml version="1.0" encoding="windows-1251"?>
<root>
<Pos>0</Pos>
<Pos>32</Pos>
<Pos>33</Pos>
</root>
. Каждый раз писать 
Код
Log<<"<root>"<<std::endl;
 тоже нельзя, так как корневой раздел xml-файла по стандарту должен быть ровно один. И прога где то виснет, так что до вывода  
Код
Log<<"</root>"<<std::endl;
 в функции main не дойдёт.

Автор: bsa 18.9.2013, 09:42
файл лога открывают один раз на все время работы программы (есть конечно варианты, но тебя они только запутают). А ты зачем-то открываешь и закрываешь при каждой записи. Это лишняя нагрузка на систему.

Автор: ТарасАтавин 18.9.2013, 11:43
Цитата(bsa @  18.9.2013,  09:42 Найти цитируемый пост)
файл лога открывают один раз на все время работы программы (есть конечно варианты, но тебя они только запутают). 
Я пробовал открывать один раз и как раз запутался. Кроме того, сейчас мне надо логировать с учётом зависаний, то есть без возможность дойти до close файла, открытого один раз. И как мне разгребать кеширование записи на диск? А открытие/закрытие каждый раз гарантирует, что я увижу ровно то состояние лога, до которого додебажил. И даже если я открою один раз, как это поможет бороться с закрывающим тегом </root>, записанным при предыдущей записи? Если же его каждый раз не писать, то лог не валиден уже из-за того, что в нём вообще нет тега </root> и таким останется до закрытия программы, то есть всегда, так как до своего закрытия она не доходит. 
Цитата(bsa @  18.9.2013,  09:42 Найти цитируемый пост)
Это лишняя нагрузка на систему. 
При минутах на одну запись лишние доли секунды на открытие/закрытие - не нагрузка. Я ведь сам читаю с браузера каждое состояние лога, анализирую его и только потом дебажу очередной шаг цикла, а это занимает время. Сейчас я вручную удаляю лишние закрывающие теги. Альтернатива, видимо, проанализировать прогу вручную, исправить, а потом также вручную добавить закрывающий тег в уже не нужном логе? Зато будет "меньше" нагрузка на систему.

Автор: SenkraD 18.9.2013, 12:02
ну можно сначала предложить плохое решении:
  • открываем файл
  • прыгаем в конец файла
  • смещаемся влево на размер тега, если возможно
  • логигруем все что нужно
 еще можно вести записи без шапки и рута, что-то типа <pos>[data]</pos>, так как большинтво библиотек, браузеров и прог поймут его как xml вполне вменяемо

вариант получше: если вам нужен xml, то может логер нужно сделать на базе того tinyxml или чего-то такого?

Автор: ТарасАтавин 18.9.2013, 13:40
Цитата(SenkraD @  18.9.2013,  12:02 Найти цитируемый пост)
открываем файл
прыгаем в конец файла
смещаемся влево на размер тега, если возможно
логигруем все что нужно
Мне бы ровно на заданное количество строк. И строки бы считать в переменную, а потом снова добавить. Как это сделать?

Цитата(SenkraD @  18.9.2013,  12:02 Найти цитируемый пост)
еще можно вести записи без шапки и рута, что-то типа <pos>[data]</pos>, так как большинтво библиотек, браузеров и прог поймут его как xml вполне вменяемо
Я теперь ещё пишу прототип текущей функции и его тег надо закрыть после лога данной функции. Так что на это полагаться нельзя.

Автор: bsa 20.9.2013, 12:41
ТарасАтавин, во-первых, если у тебя программа может повисать, то зачем ты выбрал формат xml для ведения лога? В твоем случае формат лога должен быть как можно примитивней.
во-вторых, есть такая волшебная штука - когда ты посылаешь в поток std::flush или std::endl, то содержимое потока принудительно сбрасывается на диск. Т.е. если ты виснешь после этого, то данные не потеряются.
Цитата(ТарасАтавин @  18.9.2013,  14:40 Найти цитируемый пост)
Мне бы ровно на заданное количество строк. И строки бы считать в переменную, а потом снова добавить. Как это сделать?
Прыгаешь в конец файла минус примерное количество байт на строки минус запас, затем читаешь во временный буфер, считаешь количество символов конца строки, корректируешь позицию в файле. Но это сильно скажется на быстродействии. Кому сказать, запись в лог потребляет столько ресурсов.

Как вариант, в подобных случаях можно использовать внешнее логирование - через отдельный сервис, который только логированием и занимается, а связь с ним через именованный канал или сокет. Пример: syslog и система событий Windows.

Автор: akizelokro 20.9.2013, 23:59
Ну, перейди на wfstream, вроде так по теории должен открываться файл для чтения-записи. И перейди в бинарный режим.
Найди место, с которого надо переписать, установи указатель чтения-записи (позицию), перепиши. Отсеки всё лишнее в хвосте файла, если вставка оказалась меньше по размеру заменяемого куска текста.
Задача простецкая, вроде все редакторы писали.

Автор: disputant 21.9.2013, 07:24
Цитата(SenkraD @ 18.9.2013,  12:02)
вариант получше: если вам нужен xml, то может логер нужно сделать на базе того tinyxml или чего-то такого?

У человека и так лог наверчен незнамо зачем в xml, только ресурсы жрать...

А библиотека при каждом открытии-закрытии будет поллностью парсить и полностью переписывать.

По-моему, начинать надо с того, что лог вести в обычном, простейшем текстовом формате с соответствующими флажками - сброса кэша + расшаривания для просмотра в другой программе. 

Автор: Dem_max 21.9.2013, 13:40
Может проще заюзать какой нить http://pugixml.org/documentation/

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)