Как объединить два файла на php без чтения данных из них? Т.е. создать функцию-аналог cat, чтобы обойтись только файловыми операциями, не прибегая к shell_exec.
Роман Юрьевич Ипатьев, очевидно что если я в лоб использую file_get_contents то могу выйти за пределы memory_limit.
Если я использую cat, через exec, очевидно это будет безопасно для memory_limit.
Александр Маджугин, ну так вам прекрасно известно решение без file_get_contents
Без обид, но мне кажется, что в вашем вопросе не хватает только одного - логики :)))
Окей, буду умничать, если нужно объединить файлы именно на php (лимит памяти, нельзя вызывать сторонние утилиты shell_exec и т.п.) то делать это придется по частям.
Читаем от файла сколько то килобайт в память, пишем столько же в результирующий, снова читаем кусочек... потом повторяем со вторым.
fopen
fread
fwrite
fclose
больше работы с отслеживанием граничных ситуаций (пустые или отсутствующие файлы или нехватка места)
мне кажется, что отслеживать ничего не надо. пхп обо всех проблемах проинформирует
ну разве что сделать однострочный error handler, если ошибки ФС ещё не превратили в исключения.
Пример - первого файла нет, а ты продолжишь писать данные из второго, это нормальная для задачи ситуация?
Или места на диске для записи файла нет (не фатальная ошибка) а ты продолжаешь читать данные из файлов и долбить файловую систему в попытках записать, что самое обидное у тебя иногда будет получаться, превращая итоговый файл в кашу.
Или что делать если читаемый файл в процессе увеличился в размерах (в него что то дописали)?
Отслеживать проблемные случаи зачастую правильно логично и исключает проблемы в будущем
Меня просто вымораживает это классическое пэхапе-стайл кропотливое старушечье колупание с каждой строчкой.
Вот ей-богу, как старушка с кошелкой, которая пройдет два шага, и сядет на пенёк. Откроем файл - похлопочем, а не было ли ошибки. Записали строчечку - опять похлопочем. закрыли файл - снова проверяем.
Кода обработки ошибок больше чем кода, который собственно решает задачу
Роман Юрьевич Ипатьев, к сожалению да, хотя это очень спорный вопрос, как лучше отлавливать ошибки, 'локально глобально' с помощью try catch (которые очень часто выливаются в многоуровневые конструкции, там перебросим throw, тут отловим доперебросим и т.п.) или по каждой команде скурпулезно анализировать результат, особенно это бесит когда ты пишешь асинхронный код...
в любом случае код обработки этих ошибок писать все равно придется, ведь часто бывает что просто сказать ахтунг и завершить программу - не вариант.
Отличие ваших многоуровневых конструкций, как и отслеживания проблемных случаев, от моего кода в том, что они у вас воображаемые, как проблемы у автора вопроса. А у меня код - совершенно рабочий и реальный.
Потому что сказать "надо отслеживать граничные случаи" - это не сказать ничего. Рекомендация из серии "ведите здоровый образ жизни".
Был бы какой-то реальный код со 100500 проверками - было бы о чем говорить. Вполне возможно, я бы даже принял вашу точку зрения. А так - да, поговорили о воображаемом коде, да разошлись.
Правило номер 1: если у вас есть какая-то завиральная идея, типа "а решите мне вот такую-то примитивную стандартную задачу, но только вот с такими, такими и такими ограничениями", необходимо аргументировать свою задачу. То есть объяснять причины, которые привели вас к такой постановке вопроса.
Ну вот так и надо писать. А то "черное и белое не надевать, да и нет не говорить..."
Решение очевидное - разумеется, читать из них информацию по очереди и писать в результирующий файл. Дел на 5 минут, дольше вопрос на хабр писать
Роман Юрьевич Ипатьев, у юноши стойкая идея что cat не читает файлы при объединении, а волшебные феечки через квантовое поле создают копию двух файлов в одном...
Роман Юрьевич Ипатьев, блин, вы правда думаете что это очевидная идея не пришла мне в голову? Ничего что это куча операций чтения записи и при больших объемах, дело может оказаться действительно минут на 5.
Александр Маджугин, да, я действительно думаю, что не пришла. Иначе вы бы не задавали этот вопрос, n'est-ce pas? А если у вас другой вопрос - например, конкретная проблема с кучей операций чтения и записи, которая выполняется 5 минут - то, наверное, его и надо было задать?
Ну просто мне кажется логичным, когда человек задает вопрос про ту проблему, с которой он столкнулся, а не про ту, решение которой он и так заведомо знает.
Причем желательно сразу с кодом. Который вам с удовольствием помогли бы оптимизировать
ThunderCat, не, ну в теории можно шаманить с таблицей размещения файлов. Другое дело что такое решение по сложности и багоопасности (причем таких багов, которые легко угробят всю систему на диске) настолько несоизмерима с проблемами автора (и выбранным языком программирования), что я очень, очень надеюсь, что автор и сам понимает всю его несуразность
Роман Юрьевич Ипатьев, я сам справлюсь с оптимизацией поблочного переписывания файлов с помощью file_put_contents.
Вопрос состоит именно в том, как склеить два файла не прибегая к чтению в php скрипте.
Очевидный ответ - использовать shell_exec и cat.
Александр Маджугин, короче, заканчивай фантазировать и нормально опиши проблему, без фантастики типа "файлы не читать, иф и фор не использовать" и т.п., пиши в чем задача и в чем затык.
ThunderCat, есть несколько файлов. Их надо объединить максимально быстро. Размер файлов может быть достаточно большой, поэтому тупо читать весь файл в память нельзя.
Чтение и запись кусками == большое количество операций, а значит время.
Нужны идеи.
Александр Маджугин, а вы же уже попробовали ведь? Это "большое количество операций". Эти страхи ведь у вас происходят по результатам практического применения метода, верно? Ну верно же? У вас и цифры на руках есть, правда же? Не держите в себе, поделитесь. Нам всем будет очень интересно.
есть несколько файлов. Их надо объединить максимально быстро. Размер файлов может быть достаточно большой, поэтому тупо читать весь файл в память нельзя.
Чтение и запись кусками == большое количество операций, а значит время.
1) емнип file_put_contents самый медленный из файловых методов, логичнее открыть файл на запись и бросать туда чанки, как закончишь - закрыть, будет в разы быстрее, так как при вызове file_put_contents вы каждый раз производите операцию открытия-закрытия, что нифига не бесплатно. Собсно проверить - 3 секунды рекламы, разница будет видна сразу.
2) Если у вас есть доступ к шелл - можно создать временный инмемори диск, на нем файлы собирать, а потом уже кидать на целевую партицию, это еще ускорит процесс.
ThunderCat, второе не нужно. Все ин мемори диски уже есть в ОС, называется кэш.
после того как ты прочел первый чанк с диска, с вероятностью 99% все остальные чанки будешь читать из памяти
То же самое с записью - оно все уходит во write buffer, и ОСь пишет уже в комфортном режиме сама.
Роман Юрьевич Ипатьев, да не факт, куча настроек и оптимизаций может и будет работать именно так, но голая система скорее всего нет. Хотя я так не извращался, так что наверняка не скажешь, а пробовать щас влом...
ThunderCat, насчет оси мог наврать, но по-моему практически все используют write cache, иначе система будет дико тормозить.
Но тут пыха спешит на помощь, поскольку буферизует запись тоже, причем по умолчанию. А вот если надо специально убедиться что запись произошла - то fflush().
ThunderCat, я тут полез в эту кроличью нору, и нарыл интересный подкаст с Дериком, по воводу того, как он добавил в язык fsync(), и чем он отличается от fflush()
We're talking about writing to files with fflush and fsync yep. So fflush and fsync are both about getting data out to a file, and using it to push something out of the buffers. But there are two different types of buffers; we have the application buffers; we have the operating system buffers. What fflush does is it instructs PHP to flush its own internal buffers of data that's waiting to be written into a file out to the operating system. What it doesn't do is give us any guarantee that the operating system will actually write that data to disk, so the operating system has its own buffer as well. Computers like to be efficient, operating systems like to be efficient, they will save up disk writes and do them in the order they feel like at the time they feel like. What fsync does is it also instructs the operating system to flush its buffers out to disk, thus giving us some kind of better assurance that our data has actually reached disk by the point that function returns.
Ну в общем у нас таки есть оба кэша - и пхпешный и осевой. И чтобы пропихнуть данные на диск мимо кэша - это надо ещё постараться. А по умолчанию оно спокойно пишется в буфера и уже потом - на диск.