2009-07-17 3 views
1

Я пишу программу на C, которая создает большой выходной файл. Чтобы повысить удобочитаемость, я хотел бы собирать определенные виды вывода в определенных точках файла, а не разбрасывать их случайным образом.Перемещение между двумя точками в выходном файле

Рассмотрим файл как:

log 
log 
(a) 

output 
output 
output(b) 

говорят, что программа в настоящее время пишет строку в (б). Есть ли особенно элегантный способ в C для достижения эффекта перехода к точке (a), добавления выходного сигнала линейки и возобновления нормального выхода на (b)?

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

Любые предложения были бы наиболее полезными!

+1

Требуется ли, чтобы у вас был только один выходной файл? Казалось бы, более интуитивно (и проще!) Использовать другой файл для каждого типа вывода. –

+0

Да, это необходимо. Выходной файл на самом деле представляет собой набор команд для другой программы (конкретный рисунок для чертежного набора TikZ для LaTeX). Я пытаюсь сгруппировать определенные команды, чтобы сделать вывод более понятным для человека. – Sharpie

ответ

6

Единственный способ сделать то, что вы описываете в одном файле, - это зарезервировать все пространство, которое вам потребуется для записи «журнала» спереди, что, я думаю, вы не можете сделать, потому что вы не знаете, насколько велики они будут.

Вы не можете просто вставить в файл, перемещая содержимое над точкой ввода, чтобы освободить место. Это просто не концепция, которую поддерживают обычные файловые системы. Вам нужно будет физически читать и переписывать все «выходные» фрагменты, чтобы вставить «лог», что потребует все больших и больших усилий по мере роста файла.

Лучше всего было бы написать два отдельных файла, а затем объединить их в конце.

Редактировать следующий комментарий шулер в: Поскольку выход представляет собой набор команд для программы, это значит можно смело предположить, что он никогда не будет больше, чем на пару мегабайт большой, и просто построить его в памяти, прежде чем писать все это за один раз?

+0

Наш самый большой тестовый прогон в настоящее время создает входной файл, который составляет 2,1 Мбайт, я бы предположил, что он может легко выйти на порядок выше. Похоже, что писать коллекцию временных файлов и сплайсировать их вместе, может быть, путь. – Sharpie

+1

+1 для «напишите 2 файла и присоединитесь к ним в конце» – AShelly

+0

Я проголосовал за сращивание. Если не существует способа определить, насколько долго файл будет. – NoMoreZealots

0

с fgetpos вы можете хранить указатель на позицию в файле и перейти к ней в любое время с fseek:

0

C или C++? Если C++, вы можете использовать seekp() для размещения указателя вывода. Тем не менее, это позволит вам переписать.

+0

К сожалению, мы не используем C++. Спасибо за указатель, хотя ... я обязательно проверю это, если я столкнусь с той же проблемой на C++! – Sharpie

2

Это очень необычное требование.

Один из способов: префикс дифференцирующей строки для двух видов выходных строк , а затем их записи в один файл. Если вам нужен определенный набор выходов, grep для них в объединенном файле.

output.txt ...
mark1: войти
MARK2: выход
mark1: войти
MARK2: выход
MARK2: выход

grep "^MARK1:" output.txt 
grep "^MARK2:" output.txt 

Вы в конечном итоге будет нужен файл, как вы хотели его быть написано.
Для этого вам необходимо будет отрубить префиксные строки.
В то время это было бы очень легко, если вы использовали строки, совпавшие простой регулярное выражение
Что-то подобное,

sed 's/^MARK.://g' output.txt > filtered.txt 
4

Вы не можете сделать это прямо, по очень простой причине:

Там это не способ вставить байты в середине файла. Вы можете только переписать фрагмент файла или append в конец файла.

Если вы хотите вставить в середину файла, у вас есть два варианта:

  • Читать все байты после того места, где вы хотите вставить в память. Затем напишите фрагмент, который вы хотите вставить, затем напишите все байты, которые вы кэшировали в память. Результат будет заключаться в том, что байты вставляются в данную позицию за счет произвольно большого блока памяти, чтобы удерживать кусок, который вам нужно «отбросить».
  • Кроме того, вы пишете все в новый файл. Скопируйте байты из исходного файла в новый файл. Если вы находитесь в точке, где хотите вставить новые данные, напишите новую строку. Затем продолжайте копирование из исходного файла, пока вы не закончите. Это работает, не требуя, возможно, большого объема памяти, но требует использования временного файла, в котором вы храните комбинированный результат.

...

  • В качестве альтернативы в качестве альтернативы, не написать вывод непосредственно в файл, но держать все в памяти, и записать его заказали в выходной файл, как только вы закончите сбор журнал линий.
+0

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

Смежные вопросы