Как правильно добавить строку в начало файла?

Тема в разделе "PHP Pro", создана пользователем bvb, 20 апр 2011.

Статус темы:
Закрыта.
  1. bvb

    bvb

    Регистр.:
    17 май 2009
    Сообщения:
    189
    Симпатии:
    34
    Можно ли как-нибудь добавить строку в начало, не считывая содержимое файла? То есть нужна альтернатива этому
    Код:
    $old_content = file_get_contents($file); 
    fwrite($file, $new_content."\n".$old_content); 
     
  2. Miraage

    Miraage Angular/Laravel

    Регистр.:
    3 июн 2008
    Сообщения:
    230
    Симпатии:
    51
    PHP:
    file_put_contents($file$contentFILE_APPEND);
    не оно?
     
  3. venetu

    venetu

    Регистр.:
    28 мар 2007
    Сообщения:
    735
    Симпатии:
    261
    Нет, этого сделать нельзя.

    Для того, чтобы по-быстрому добавить в начало файла на системах типа FAT, надо перенести стартовый кластер в другое место (запись в таблицу размещения файлов и в ее копию) и заполнить этот стартовый кластер своей начальной строкой (вторая запись). Причем строка будет строго по размеру кластера (т.е. от 512 байт до 32Кб в зависимости от того, как отформатировано устройство).

    На NTFS можно создавать NTFS Streams, но в данном случае они никак не помогут. На линуксовых ext2 и ext3 все в теории так же, как и для FAT, только ограничение явно в 512 байт. Так что может быть для тебя это будет и выход (будешь дополнять пробелами свою строку, например. Или дописывать в начало ее реальную длину а при считывании отсекать).

    Ну и в любом случае, ты ошибся разделом. Подобные манипуляции требуют низкоуровневых обращений к диску и вообще, гемор еще тот.

    Я бы пересмотрел саму схему хранения данных, например вместо одного файла завел бы два (индекс+данные) и реализовал бы процедуру экспорта из этих двух в один последовательный файл. Тогда у тебя и вставки будут происходить быстро - в начало, в конец, в любое место, и данные можно будет хранить большого объема, и связь с внешним миром не потеряется.
     
    trooll нравится это.
  4. saen

    saen

    Регистр.:
    6 авг 2006
    Сообщения:
    756
    Симпатии:
    129
    Это добавление в конец файла. По умолчанию файловый указатель находится в конце файла. Если его переместить вначало и что-либо записать, все что ниже сотрется. Того что написал ТС без чтения сделать нельзя.
     
  5. rex1963

    rex1963

    Регистр.:
    19 фев 2007
    Сообщения:
    228
    Симпатии:
    47
    Это принципиально, чтобы запись проводилась именно в начало файла, или это нужно для последующего вывода последний-первый?
    Здесь довольно популярно написано _http://kurepin.ru/php/zametki/add_str/

    Если нужно только для вывода на экран, пиши в конец файла и делай
    PHP:
    $lines array_reverse(file('u.txt'));

    // Осуществим проход массива и выведем номера строк и их содержимое в виде HTML-кода.
    foreach ($lines as $line_num => $line) {
        echo 
    "Строка #<b>{$line_num}</b> : " htmlspecialchars($line) . "<br />\n";
        

    }
     
  6. saen

    saen

    Регистр.:
    6 авг 2006
    Сообщения:
    756
    Симпатии:
    129
    как минимум быдлокод
     
  7. venetu

    venetu

    Регистр.:
    28 мар 2007
    Сообщения:
    735
    Симпатии:
    261
    Я говорю, индексы тебя спасут!

    Filepos:StringSize:NextIndex
    Filepos:stringsize:NextIndex
    ....

    Тупо бинарный файл по три unsigned int на каждую строку (у тебя ведь файл с данными не больше 4Gb?). StringSize и NextIndex можно вообще-то и short взять, в целях экономии. Памяти в PHP меньше жрать не станет, а размер файла с индексом сократится. StringSize можно вообще выкинуть, если у тебя в данных и так есть ограничители (перевод строки, к примеру). Итого оверхед - 6 байт на строку. А скорости прибавится, и рандомный доступ, и чтение-запись, и вообще, хоть в середину теперь свои строки вставляй - весь файл переписывать не надо, только два аппенда и оверрайт этих 6ти байт в индексном файле. Идеально!
     
    trooll нравится это.
  8. Miraage

    Miraage Angular/Laravel

    Регистр.:
    3 июн 2008
    Сообщения:
    230
    Симпатии:
    51
    что-то я под порохом написал бреда :D
    вот как-то так
    PHP:
    /**
     * Добавить содержимое в начало файла
     *
     * @param  string  $filename - Файл, куда добавляем
     * @param  string  $content - Содержимое, которое нужно добавить
     * @param  boolean $newline - [Опционально] Добавить разрыв строки?
     * @return integer - Длина записанной строки
     */
    function file_put_contents_prepend($filename$content$newline FALSE)
    {
        
    $current file_get_contents($filename);
        if (
    $newline === TRUE$content "\n" $content;
        return 
    file_put_contents($filename$content $current);
    }
     
  9. venetu

    venetu

    Регистр.:
    28 мар 2007
    Сообщения:
    735
    Симпатии:
    261
    Чувак же просил не считывая весь файл, а у тебя file_get_contents.

    Короче мое резюме - нет, так просто дописать к началу произвольного файла текст не получится. Или придется считывать и перезаписывать весь файл (1), или это будет не произвольный файл (2), или надо очень заморочено переставлять кластеры на низком уровне (3) - и работать это будет с большими ограничениями и только на конкретной файловой системе. Кроме этих трех других вариантов не вижу.
     
  10. trooll

    trooll PHP кодер

    Регистр.:
    22 дек 2008
    Сообщения:
    503
    Симпатии:
    116
    bvb --- Э-з-з не вдаваясь в технические подробности, которые ты не осилишь, то что ты хочешь сделать тяжело реализуемо. Имхо **х. лишней гемор.

    В свое время тоже как то марочился с этой проблемой дня 2, в итоге забил овчинка выделки не стоит, меняй архитектуру работы с файлами в своих проектах, дешевле будет;)

    venetu - красавчик:ay: умеешь вынести мозг, и поднять настроение. Представляю как у ТС все перевернулось в мозгу после прочтение твоего первого и второго поста в топике. ТС Хотел увидеть готовое решение, но получил полную *опу огурцов...:D

    Как говориться искореним незнание, непонятными терминами и мат. частью, научим пользоваться поиском, и просто надаем подзатыльников, обращайтесь, не дорого, постоянным клиентам скидки:D
     
Статус темы:
Закрыта.