Смысл простой, есть файл (допустим 100-200мб) и надо удалить из него отрывок (offset и динна извесны зарание) как это удобнее сделать ? (чтоб сервак не задосить...)
Идей полно, начиная от fopen()>>fread()>>fseek()>>fwrite()>>fseek() и до fopen(1)>>fopen(2)>>fread(1)>>fwrite(2)>>unlink(1) но интересует это всё дело так чтоб нагрузка была минимальной (время выполнения значения не имеет, лишь бы с объёмом памяти проблем не было)
Я бы пошел одним из двух путей: 1) (простой) чтение с записью блоками по 8К - немного долго, совсем чуть-чуть нагрузка на проц, память не забивается (если не считать накладных расходов на кеширование ввода/вывода системой) 2) Поскольку fseek возможен, значит записи равной длины. Значит можно делать как в DBF - помечать запись как удаленную, но не удалять ее до процедуры чистки. В этом случае потребуется изменить кусок который читает этот файл - на предмет игнора записей помеченных не удаление...
fseek возможен не потому что записи равной длины, а потому что информация о том где запись начинается и какой она длинны есть в другом файле Так оно сейчас и есть, и именно о процедуре чистки я и спрашиваю как её лучше проводить. Пока склоняюсь как раз в варианту (длинна блоков будет браться исходя из длинны "неудалённых" записей)
опятьже два метода: 1) Создаем второй "чистовой" файл без удаленных записей, потом переименовываем. Требует дисковое пространство, зато нет вероятности потери данных если процедура не завершится по какой-то причине. 2) Все делаем в одном файле. Читаем до первой удаленной записи, с этого момента накапливаем буфер в 32К состоящий из чистых записей, запихиваем его в запомненную позицию и смещаем указатель "получатель" на размер буфера... И т.д. Хвост файла транкейтим. Не требует доп.места. Довольно быстро. Но если что-то обломится по ходу - все пропало...
[offtop] Пришла в голову... не могу оценить какая, но мысль... Что если файлы засунуть в БД. Причем сделать это с разбиением на блоки, например назаначить стандартный кусок 1024К. Таким образом файл из 200 метров будет записан как 200 записей в таблице. У каждой записи должно быть поле size, содержащие размер блока. Следовательно что нам нужно. Нам нужно определить нужный блок и выризать из него нужный кусок, при этом изменив size на реальный размер. Сложность возникнет когда нужный для редактирования кусок будет растянут на 2 или более блоков, но это решаемо. Если бы я решил так замарочиться я бы сделал для этого дела класс, в котором сделал бы функции редактирования чтения блоков и чтения всего файла... Самому мне мысль кажется немного бредовой, но... не знаю, не знаю какие перед тобой задачи стоят. Если ты намерен править часто большие файлы, то наверное это то что тебе надо, если ты намерен чаще их отдавать пользователям, то наверное этот вариант не подойдет тебе... потому что тогда все равно правильнее будет сохранять файл и отдавать его без участия пхп. А следовательно выполнять посути тоже что ты мог сделать из вышеописанного. [/offtop]
Горбунов Олег Не надо оскорблять меня, гостевая это лишь "побочный" скрипт я же уже давно занимаюсь другими вещами. Передомной стоит задача удаления файлов из архивов, удаление записей из моей "супер гостевой", удаление фрагментов из AVI файлов, а точнее мне нужно провести операцию по удалению фрагмента файла при том что фрагмент имеет строго заданную длинну и находится в строго заданном месте, использование БД исключено ибо простота залог безглючности...
Не хочется разводить холивар "файлы vs базы" но могу сказать лишь одно, есть случаи когда использование файлов не хуже базы. Например для упомянутой выше гостевой книги использование файлов вместо базы даёт только несколько минусов часть из которых легко решаются, а часть из которых и не нужно решать. Слабое быстродействие например легко преодалеть с помощью оптимизации кода... А уж в некоторых случаях база просто будет мешать...
Да... это точно... седня у моего хостера упал мускуль)))) и я лично в этом убедился...)) Но молодцы, быстро подняли)
Vladson, для разовой работы моя мысль тебе совсем никак не подходит. ИМХО: не в тему замечание. Я привел мысль как при многократном обращении на изменение больших файлов не делать чтение огромных файлов чтобы изменить в них строчку. Допустим у тебя есть 5 файлов по 200 Мб. На выбор - прочитать 1 гб или прочитать 5 забисей по 1-у мегабайту. Естественно мою мысль можно реализовать и файлами, но это уже изврат. С пяти файлов, мы получаем 1000 файлов, с 20 файлов по 200Мб получаем 40000 файлов... нагрузка на файловую систему будет такая, что плохо станет Нужно всего лишь знать/чувствовать где что лучше применть. Накпример, движок состоит из 150 пхп файлов из них 60 требуются для работы любой страницы, следовательно проще сделать объединение этих фалов в один. Вот пожалуйста пример работы с файлами, заметь я не предлдожил их засунуть в базу . У меня кривые, я тоже так умею
А если не многократное а однократное ? (раз в месяц например) Сейчас ситуация такая что есть файл где хранятся много маленьких записей, каждая запись строго журналируется и при удалении удаляется не запись а только запись о её присутсвии (как удаление файлов в FAT) так вот речь о том как проводить "чистку" (что-то типа дефрагментации в FAT) Скрипт на хостинг где нет мускула, как уже были примеры есть люди которые не имеют даже одного бакса на нормальный хостинг Опять-же блог где записи читаются линейно по несколько последних записей без сложных выборок а коментарии даже не имеют постраничной разбивки Любые другие скрипты где все сложные механизмы присутсвуют только при добавлении записей а чтение идёт линейно Я могу продолжать вечно
Вот тут хочется сделать одно очень интересное отступление... Я не против использования баз как таковых ! Более того я очень люблю MySQL причём даже "тройку" (я даже не говорю про "пятёрку") они очень грамотно сделаны и позволяют каждому ламеру вытворять такие фишки что многим даже опытным программистам не снились. (Это я о скорости работы и загрузке проца при выборке из нескольких таблиц со сложными зависимостями.) На файлах реализовать такое хоть и теоретически возможно но ресурсы жрать этот велосипед будет как межплаиетный карабль. Однако есть случаи когда сложная выборка не нужна, иногда для отображения страницы всё что нужно это 5-10 последних новостей/статей/итд (которые добавляются пару раз в день а ресурсоёмкость их добавления не имеет значения) проще кешировать результат в файле и доставать от туда. К примеру функция PHP: <?php $array = unserialize(file_get_contents('news.tmp')); ?> будет намного быстрее работать чем PHP: <?php $array = array(); $result = mysql_query('SELECT * FROM `news` ORDER BY `date` DESC LIMIT 0, 10;', $link); while($temp=mysql_fetch_assoc($result)) $array[] = $temp; mysql_free_result($result); ?>
тогда генерируется код и кешируется, а доставание кеша из базы все равно будет быстрее чем из файловой системы. =)
Во первых не всегда MySQL и Apache находятся на одном (физическом) сервере Во вторых база бывает нагружена (особенно на shared-хостинге) В третих есть страницы котороые вовсе при файловом кеше не будут даже ссоединяться с базой а в любом описаном выше случае ссоединение уже является долгой и мучительной процедурой. Короче говоря не все могут себе позволить свой сервер, и иногда приходится крутиться.
Vladson если генерировать целиком страницу в HTML, то да. это переплюнет базу. согласен. а в случае кускового кешироания, думаю, доставание из базы будет быстрее файла, при условии что база используется помимо этой операции.
То, что файлы порой - очень просто и удобно видно из успеха DokuWiki. Лично у меня на всякий пожарный имеется свой модуль по хранению информации в файлах, с очень простыми инструментами выборки, но в определённых задачах оно себя оправдывает, и кое-где я его использую. Хотя всё же пользуюсь им крайне редко, а с появлением sqlite в php5 о нём вообще можно забыть (за исключением ситуаций, когда пишешь не под php5, но это для меня уже вчерашний день).
Сразу видно ты не часто пользуешься хостерами за 2-3 бакса в месяц Когда у меня был сайт HeatPC его часто досили, так вот тогда ссоединение с базой являлось не просто долгой и мучительной процедурой, но и вовсе чем-то невообразимым