Як видалити рядок з файлу

Як видалити рядок з файлу

При роботі з невеликими об’ємами даних на мові PHP іноді буває простіше зберігати їх у файлах, ніж створювати базу даних та організувати взаємодію з нею скриптів. У таких випадках завдання з видалення заданих рядків з текстового файлу виникає не рідко. Розберемо в подробицях по можливості найбільш простий спосіб зробити це.

Вам знадобиться

Початкові знання мови PHP

Інструкція

  1. Вихідні дані:

    - Маємо текстовий файл allStrings.txt, який містить певну кількість рядків даних

    - Потрібно видалити з файлу рядок № 44

    Алгоритм вирішення поставленого завдання буде таким: потрібно відкрити файл, прочитати їх містить рядки в масив рядків і переписати існуючий файл вмістом масиву, пропустивши рядок, призначену для видалення.
  2. Для реалізації цього алгоритму в скрипті спочатку привласнимо значення змінним, які будуть містити ім’я вихідного файлу і номер рядка, засудженої до видалення:

    $ FileName = «allStrings.txt»;

    $ LineToKill = 44;

    Потім прочитаємо файл в масив рядків:

    $ StringsArray = file ($ fileName);

    Перевіримо чи є у файлі потрібна нам рядок. Весь подальший код буде виконуватися тільки якщо виконана умова $ lineToKill не більше, ніж кількість рядків у масиві $ stringsArray:

    if ($ lineToKill

    / / Тут буде основний цикл програми

    }

    Якщо умова не виконана, то видаляти нам нічого. Нехай скрипт надрукує інформаційне повідомлення про це:

    else echo «Кількість рядків у файлі менше». $ lineToKill. «!»;

    Якщо ж умова виконана, слід очистити вихідний файл для нового запису:

    $ FileHandle = fopen ($ fileName, «w»);

    Тепер нам слід організувати цикл, перебирающий всі елементи масиву рядків. Але оскільки індексація масиву починається з нуля, а номер рядка для видалення ми відраховували від одиниці, то ще до початку циклу зменшимо значення $ lineToKill на одиницю, щоб не повторювати цю операцію на кожному кроці:

    $ LineToKill -;

    Поря організувати цикл:

    foreach ($ stringsArray as $ key => $ value) {

    / / Тут код кожного кроку циклу

    }

    Змінна $ key буде містити індекс поточного рядка в масиві, а змінна $ value — значення цього рядка. У кожному кроці циклу будемо порівнювати індекс рядка в масиві з номером, призначеним на видалення і якщо вони не збігаються, то будемо записувати значення цього рядка у файл:

    if ($ key! = $ lineToKill) fwrite ($ fileHandle, $ value);

    А якщо збігаються, то записувати в файл не будемо, а надрукуємо повідомлення про успішне видалення:

    else echo «Рядок». $ lineToKill. «видалено.»;

    І після закінчення роботи циклу, коли буде закінчена і запис в файл, слід ввічливо закрити його:

    fclose ($ fileHandle);
  3. Весь код в зборі буде виглядати так:

    $ FileName = «allStrings.txt»;

    $ LineToKill = 44;

    $ StringsArray = file ($ fileName);

    if ($ lineToKill

    $ FileHandle = fopen ($ fileName, «w»);

    $ LineToKill -;

    foreach ($ stringsArray as $ key => $ value) {

    if ($ key! = $ lineToKill) fwrite ($ fileHandle, $ value);

    else echo «Рядок». $ lineToKill. «видалено.»;

    }

    fclose ($ fileHandle);

    }

    ?>

    Зрозуміло, це найпростіший код, у котрому немає захисту від усіх ускладнень, які можуть статися в процесі роботи скрипта в реальних умовах. Наприклад, якщо файл містить гігантську кількість рядків, то читання їх в масив отгризет від ресурсів сервера недозволено великою для одного скрипта шматок. Звичайно, роботу з великою кількістю даних слід організовувати через бази даних, а не текстові файли. Але все ж, як навчальний приклад, наведемо код, вирішальний і це завдання. Тут алгоритм буде відрізнятися від попереднього: щоб не зберігати величезну кількість рядків у масиві, скрипт буде читати з вихідного файлу по одному рядку і по одній записувати їх у тимчасовий файл. Після закінчення цього процесу вихідний файл буде видалено, а тимчасовий файл буде переміщений на його місце.
  4. Починатися цей скрипт буде так само, як і попередній:

    $ FileName = «allStrings.txt»;

    $ LineToKill = 44;

    Потім для роботи потрібно створити тимчасовий файл. Зробимо це в папці «tmp» і префікс тимчасового файлу дамо такий же:

    $ TempFile = tempnam («/ tmp», «tmp»);

    Тепер спробуємо відкрити вихідний файл для читання:

    if ($ fileHandle = @ fopen ($ fileName, «rb»)) {

    / / Цей код буде виконаний у разі нормального відкриття вихідного файлу

    }

    Якщо цього зробити не вдасться — подальша робота скрипта не має сенсу, уб’ємо процес з видачею відповідного повідомлення:

    else die («Вихідного файлу не існує!»);

    Якщо файл відкрився нормально, то надрукуємо оповіщення про це і спробуємо відкрити раніше створений тимчасовий файл з видачею відповідного повідомлення:

    echo «Вихідний файл існує»;

    if ($ tempHandle = fopen ($ tempFile, «w»)) echo «Тимчасовий файл був створений.»;

    Тепер пора починати цикл читання рядків з вихідного файлу, який буде тривати, поки не упреться в закінчення файлу:

    while (! feof ($ fileHandle)) {

    / / Тут буде код роботи з поточним рядком

    }

    На кожному кроці циклу будемо читати один рядок:

    $ LineToWrite = fgets ($ fileHandle);

    І якщо це не той рядок, яку треба видалити, то записувати її в тимчасовий файл. Лічильник рядків $ lineNum буде збільшуватися безпосередньо в операції порівняння:

    if ($ lineToKill! = (+ + $ lineNum)) fwrite ($ tempHandle, $ lineToWrite);

    Коли рядки закінчаться, закриємо про файл:

    fclose ($ fileHandle);

    fclose ($ tempHandle);

    І на закінчення перейменуємо тимчасовий файл у вихідний. Якщо і ця операція буде вдала, то видамо відповідне повідомлення:

    if (rename ($ tempFile, $ fileName)) echo «Рядок $ lineToKill видалена»;
  5. Весь код в зборі: $ fileName = «allStrings.txt»;

    $ LineToKill = 44;

    $ TempFile = tempnam («/ tmp», «tmp»);

    if ($ fileHandle = @ fopen ($ fileName, «rb»)) {

    echo «Вихідний файл існує»;

    if ($ tempHandle = fopen ($ tempFile, «w»)) echo «Тимчасовий файл створений.»;

    }

    else die («Вихідного файлу не існує!»);

    while (! feof ($ fileHandle)) {

    $ LineToWrite = fgets ($ fileHandle);

    if ($ lineToKill! = (+ + $ lineNum)) fwrite ($ tempHandle, $ lineToWrite);

    }

    fclose ($ fileHandle);

    fclose ($ tempHandle);

    if (rename ($ tempFile, $ fileName)) echo «Рядок $ lineToKill видалена»;

    ?>