Верно ли, что нельзя дописать что-то не в конец файла, не перезаписав файл? Как поступают, например, стандартные парсилки/редакторы XML (в любом языке программирования) если я вставляю значение поля в середине файла? Перезаписывают весь файл или только то, что после редактируемого места?
4 Answers
И верно и неверно. В общем случае верно. Файл с точки зрения приложения представляет собой непрерывный кусок дисковой памяти. Запись в середину неминуемо приводит к затиранию существующих данных. Обычно программы либо перезаписывают файл целиком, либо начиная с точки изменения и до конца.
Однако, существует путь вставки данных в середину файла без перезаписи. Как известно, данные на диске хранятся в виде блоков и файл представляет собой совокупность блоков, причём где-то может храниться карта блоков для файла, либо же каждый блок содержит ссылку на последующий. Можно создать новый блок, записать в него данные и поменять карту, вставив ссылку на блок. Но у такого подхода есть и недостаток. Либо мы должны вставлять данные блоками определённого размера, либо использовать только часть блока и мириться с потерей части дисковой ёмкости.
Почти любые стандартные и нестандартные средства работают не напрямую с диском или файловой системой тома, а обращаются с запросами на действие к файловому реквестору. Тот соответственно транслирует файловые операции в дисковые (и обратно), инициируя чтение или запись физических секторов.
Если файл полностью считывается в память процесса и потом полностью записывается обратно, то дисковая подсистема тупо выполнит всё запрошенное, и запишет старую информацию поверх новой, несмотря на то, что в ней ни бита не поменялось (это я про "голову файла" до точки внесения изменений) - так дешевле, чем сравнивать то, что было, с тем, что стало.
Но если процесс считывает некоторое "окно", в которое вносятся изменения, и затем это новое состояние сбрасывается на диск, то перезаписыванию подвергнутся только секторы, которые относятся в этому окну. И именно приложение, чтобы не поломать файл, вынуждено будет организовывать чтение следующих "окон", смещение в них информации и запись их нового состояния - и так до конца файла. Процесс, как понимаете, дорогой, а память нынче дёшева - потому подавляющее большинство приложений не занимаются подобным "крохоборством" и для изменения читают, а после изменения пишут, весь файл целиком.
А чтобы при этом не нарваться на проблемы, предпочтительным является не перезапись поверх, а запись нового файла с переименованием и/или удалением старого. Поиск свободного пространства под файл, по возможности непрерывного - тоже недорогая операция, так что новый файл скорее всего окажется физически совсем не в том месте, где лежал файл до корректировки. А заодно такая методика является и пассивным методом борьбы с фрагментацией.
- 31,807
Стандартные парсилки/редакторы XML считывают файл полностью в оперативную память, а потом также полностью записывают его на диск. Для компьютера это гораздо проще и быстрее. Если работать напрямую с жестким диском, то это будет ОЧЕНЬ медленно.
- 326
- 1
- 7
-
-
-
@Harry Если файл несколько гигабайт, что лучше поискать другой формат для хранения. Как вариант можно попробовать разбить xml на несколько частей, потом загружать в память какие-нибудь заголовки или вводные слова для каждой части. По этим словам находить нужную тебе часть и загружать её в оперативку, чтобы с ней работать. В самом конце склеивать файлы в один большой XML. Хотя это тоже не очень хороший вариант в плане скорости, но хоть какое-то решение. – evilnw Dec 19 '16 at 08:33
-
@evilnw, а можно ссылку на доку какой-нибудь стандартной, где об этом сказано? – G0ohan Dec 21 '16 at 03:37
-
1@G0ohan, к сожалению, я даже не смогу найти. Когда-то давно читал статью, где похожим способом пытались обойти ограничение на количество оперативной памяти, но там всё гораздо хуже. Было устройство, у которого всего 5 мб оперативной памяти и требовалось парсить разные таблицы и тексты, которые могли занимать по 10-20 мб. Основной файл разбивался на кучу маленьких и на каждый такой файл вешались вводные слова, по которым можно быстро найти нужную часть. Далее программа открывала этот небольшой файл и доставала\записывала нужные значение. В конце все файлы собирались в один. – evilnw Dec 21 '16 at 05:24
Да, верно.
Зависит от реализации. Вполне допускаю, что файл полностью считывается в память, обрабатывается и полностью сбрасывается на диск.
- 221,325
fallocate()не просто отдельные байты позволяют переписывать, по месту не копируя—эта функция позволяет менять длину файла (с ограничениями вставлять/удалять, в том числе и в середине). – jfs Dec 20 '16 at 02:41