2013-03-01 3 views
1

У меня есть FILE* file, который содержит некоторые двоичные данные. Предположим, что эти данные являются списком double и последняя запись представляет собой строку, которая описывает, что такое double. Я хочу изменить эту строку (новая строка может быть короче). Поэтому сначала я удаляю старую строку. Мне нужно найти начальную точку строки:Обрезать или изменить размер файла, чтобы изменить его конец

fseek(file,-size(sring.size()),SEEK_END); 

а затем что мне делать? я нашел Delete End of File ссылку, но я не знаю, какой из них использовать ... Как только файл будет изменен, я могу просто написать свою новую строку, используя fwrite?

ответ

4

Ни FILE* ни утопление поддержки iostream. Если вы хотите редактировать файл так, что новый файл короче, чем старый, вы есть два решения:

  • Обычное решение скопировать исходный файл в новый файл, внесение каких-либо изменений как вы идете. Когда закончите, закройте новый файл , убедитесь, что нет ошибок (важная точка), , затем удалите исходный файл и переименуйте в новый файл, чтобы иметь исходное имя . Это может вызвать проблемы в Unix-системах, если были жесткие ссылки на исходный файл. (Как правило, этот не является проблемой, так как теперь все используют софт-ссылки. Если это так, вы должны указать stat оригинал, а если поле st_nlink - больше 1, скопируйте новый файл на оригинал, а затем удалите новый файл.) С другой стороны, это самый общий вариант ; он работает для всех типов модификаций, где угодно в файле .

  • На нижнем уровне обычно используются системные функции для усечения файла. В Unix это ftruncate. Но вам нужно будет найти количество байтов, где вы хотите обрезать ; ftruncate требует открытого файла, но он не будет обрезать в текущей позиции в файле. Таким образом, вам нужно будет 1) найти начало этой последней строки в файле, 2) искать его, 3) записать новое значение, 4) позвонить ftell (или ftello, если длина может быть слишком большой для установки на long), чтобы найти новую конечную позицию. На этом этапе у вас возникла проблема синхронизации вашего FILE* с нижним уровнем; лично, я бы fclose файл, , а затем заново открыть его open и сделать ftruncate на файл дескриптор с этого открытия.(На самом деле, лично я бы делать всю работу с помощью open, read, lseek, write, ftruncate и close. А может быть, stat узнать длину файла до фронта. Если вы не должны переводить двойники, там действительно ничего, что добавляет FILE*.

Как правило, я бы с первым раствором, и только попробуйте второй, если он оказывается слишком медленным. (Если файл содержит пару миллиардов удвоений, например, копирование их займет некоторое время.)

+0

отличный ответ, но он поднимает несколько вопросов для второго решения, которое вы предложить. вы имеете в виду, что мне нужно сначала сфотографироваться, а затем найти, где я хочу усечь, затем fclose, open why? почему я не могу оставить файл открытым? и что вы подразумеваете под «Если вам не нужно переводить двойники, то действительно ничего не добавляет FILE *». – PinkFloyd

+0

Связано это с комментарием, который вы даете @ aaaaaa123456789? – PinkFloyd

+0

@ user2110463 Второй вопрос во-первых: что '' (и iostream) действительно добавить к вашему основному системному уровню IO 1) переносимость 2) разбор различных типов ввода ('double', ' int' и т. Д.) , Если вам не нужен последний, и вы используете 'ftruncate', то у вас нет первого, вы можете также сделать все с точки зрения базового уровня системы ввода-вывода. –

4

Если вы хотите изменить размер файла, то ftruncate() (http://www.linuxmanpages.com/man2/ftruncate.2.php) - это функция, которую вы ищете. Вам нужно будет позвонить fileno() в структуру FILE *, чтобы получить файловый дескриптор для ftruncate().

Что касается добавления новых данных (новой строки) после уменьшения размера файла, просто поиск конца (fseek(file, 0, SEEK_END)) и fwrite() 'IN должен сделать это.

EDIT: не забудьте позвонить fflush(), прежде чем обрезать файл!

+0

большое спасибо! но действительно ли мне нужно искать конец после ftruncate()? он должен уже на правильном месте!? – PinkFloyd

+0

извините глупый вопрос! – PinkFloyd

+1

Нет сомнений, что это глупо, если это действительно происходит из-за недостатка знаний. Все ничего не знали ни разу. Что касается того, почему (в случае, если кто-то интересуется тем же, или если вы неясны), это связано с тем, что указатель файла по-прежнему указывает на то, где он указывал - не обязательно на новый конец файла. Даже если это так, это хорошая практика программирования для 'fseek()' в любом случае, на всякий случай. – aaaaaa123456789

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