Напишите циркулярный файл на С ++ - PullRequest
8 голосов
/ 20 мая 2009

Мне нужно написать циркуляр на C ++. Программа должна записывать строки в файл, а когда код достигает максимального количества строк, она должна перезаписывать строки в начале файла.

У кого-нибудь есть идеи?

Ответы [ 13 ]

0 голосов
/ 20 мая 2009

Простой обходной путь:

  • Определите максимальную длину 80 символов в строке. оберните более длинные «строки» в несколько строк.
  • Добавить заголовок строки в строку. например, «[# 589] Это 589-я строка», поэтому вы будете знать, что будет первым и т. д.
0 голосов
/ 20 мая 2009

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

logFile.lockForWrite();
currentPosition = logFile.getWritePosition();
logFile.seek(currentPosition);
for each line in lineBuffer {
    if ((currentPosition+line.length()) > logFile.getMaxSize()) {
        currentPosition = 0;
        logFile.seek(0);
    }
    logFile.write(line);
    currentPosition += line.length();
}
logFile.setWritePosition(currentPosition);
logFile.unlock();

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

lastPosition = logFile.getWritePosition();
while (!killed) {
    logFile.wait();
    logFile.lockForRead();
    newPosition = logFile.getWritePosition();
    logFile.seek(lastPosition);
    newLine = logFile.readFrom(lastPosition, (newPosition-lastPosition));
    lastPosition = newPosition;
    logFile.unlock();
}

Это не на каком-то конкретном языке - это просто псевдокод, но идея есть. Конечно, я оставил читателю обработку всех интересных крайних случаев.

С учетом всего сказанного ... Я согласен с другими мнениями. Не делайте этого, если у вас нет действительно веской причины. Звучит как отличная идея, но:

  • Реализация трудна для получения записи
  • еще эффективнее сделать
  • поскольку позиция записи должна где-то сохраняться, несколько утилит должны согласовать, как она читается, обновляется, инициализируется и т. Д.
  • наличие нелинейного журнала затрудняет обработку журналов с использованием существующих инструментов, таких как grep, tail, perl и т. Д.

В целом, вам будет лучше использовать какой-нибудь существующий пакет регистрации пакетов, который позволяет настраивать управление файлами журналов. Взгляните на Apache log4cxx или Poco's Poco::Logger.

0 голосов
/ 20 мая 2009

это будет сложно, поскольку файловый ввод / вывод работает с байтами в качестве базовой единицы хранения, а не с строками.

Я имею в виду, что вы можете просто выполнить fseek () назад и начать обрабатывать более ранние данные, но у меня есть догадка, что вы не хотите этого.

...