PHP: как удалить последний разрыв строки из текстового файла?

В школьной работе я создал сайт для вымышленного космического музея в моем городе, используя PHP. В нем есть системы включения данных и консультации данных, но у меня есть проблема с консультацией, которую я хочу знать, как решить: как удалить последний разрыв строки из файла?

Включение данных

В закрытой зоне сайта у меня есть форма HTML5 с 5 полями (имя, адрес, номер телефона, пол и посещенные выставки), которая отправляет данные методом POST в функцию на PHP, которая записывает их в заданный текстовый файл. с помощью команды fwrite:

fwrite ($pointer, "$name | $addres | $telephone | $sex | $exhibitions " .PHP_EOL);

Как видите, он записывает в txt-файл данные, введенные в форму, плюс разрыв строки. Указатель — это переменная, используемая fopen для открытия файла, который мне нужен для работы. Пример вывода:

Марсио Агиар | улица Бельмиро Брага | 1234-5678 | М | Планеты Солнечной системы
Джоана Тобиас | Сантос-Даммонт-авеню | 8765-4321 | Ф | Черные дыры, спутники

Консультация по данным

Далее идет система консультаций. Он имеет цикл, который выполняется до тех пор, пока файл не закончится. Внутри этого цикла есть переменная с именем $buffer, которая каждый раз получает одну строку txt-файла. Затем exploded создает массив с именем $lines[$counter]. Чтобы напечатать его красиво, я использую array_combine, где я соединяю имена полей в другом массиве ($keys) со значениями, записанными в $lines[$counter], и связываю это с $combined[$counter]. Затем цикл завершается, и я использую print_r внутри <pre></pre>, чтобы увидеть данные, записанные в $combined, сохраняя при этом пробелы и разрывы, которые в противном случае HTML проигнорировал бы. Вот код:

$keys = array ("Name", "Address", "Telephone", "Sex", "Visited exhibition");
for ($counter=0;!feof($reader);$counter++){
    $buffer = fgets($reader);
    $lines[$counter] = explode(" | ", $buffer);
    $combined[$counter] = array_combine($keys, $lines[$counter]);
}
echo "<pre>";
print_r($combined);
echo "</pre>";

Пример вывода:

    Array
    (
    [0] => Array
        (
            [Name] => Márcio Aguiar
            [Address] => Belmiro Braga Street
            [Telephone] => 1234-5678
            [Sex] => M
            [Visited exhibitions] => Planets of Solar System 

        )

    [1] => Array
        (
            [Name] => Joana Tobias
            [Address] => Santos Dummont Avenue
            [Telephone] => 8765-4321
            [Sex] => F
            [Visited exhibitions] => Black Holes, Satellites 

        )

    [2] => 
    )

Здесь вы можете видеть, что массив 2 был создан пустым. Это вызвано последней строкой, которая содержит только разрыв строки, вставленный формой выше. Мне нужно убрать этот последний разрыв строки, и только тот, но не знаю как. Я хочу знать! Незнание приводит к отображению ошибки, когда выполнение достигает array_combine, потому что необходимо, чтобы два массива имели одинаковое количество элементов, а 2 было пустым. Здесь ошибка:

Предупреждение: array_combine(): Оба параметра должны иметь одинаковое количество элементов в E:\Aluno\Documents\Wamp\www\trab_1\area_restrita\consulta.php в строке 60.


person Anders    schedule 04.05.2015    source источник


Ответы (3)


Исходный ответ:

Чтобы удалить разрыв строки в конце любого текста, вы можете использовать trim(), однако в вашем случае вам просто нужно использовать fopen в режиме добавления :

$handle = fopen("/path/to/file", "a");

Затем избавьтесь от PHP_EOL:

fwrite ($pointer, "$name | $addres | $telephone | $sex | $exhibitions");

Изменить. Вы правы в том, что добавление не добавляется к новой строке. Я ошибался. Таким образом, вы можете использовать функцию trim(), как я упоминал ранее. Я создал быстрый пример, используя file_get_contents() и file_put_contents(), и, похоже, он делает то, что вы хотите:

<?php

$file = 'test.txt';

// Set existing contents (for testing sake)
$orig_contents = "bob | 123 fake street | 1234567890 | yes, please | no\n";
$orig_contents .= "bob | 123 fake street | 1234567890 | yes, please | no\n";
$orig_contents .= "bob | 123 fake street | 1234567890 | yes, please | no\n";
$orig_contents .= "bob | 123 fake street | 1234567890 | yes, please | no\n";
file_put_contents($file, $orig_contents);

// Here is how you could add a single new line with append mode
// Notice the trailing \n
file_put_contents($file, "billy | 456 fake street | 2345678901 | no | yes\n", FILE_APPEND);

// Get contents from the file and remove any trailing line breaks
$contents = trim(file_get_contents($file));

$keys = array ("Name", "Address", "Telephone", "Sex", "Visited exhibition");

// Explode based on the new line character
$lines = explode("\n", $contents);

foreach ($lines as $line) {
    $values = explode(" | ", $line);
    $combined[] = array_combine($keys, $values);
}

print_r($combined);

Это печатает:

Array
(
    [0] => Array
        (
            [Name] => bob
            [Address] => 123 fake street
            [Telephone] => 1234567890
            [Sex] => yes, please
            [Visited exhibition] => no
        )

    [1] => Array
        (
            [Name] => bob
            [Address] => 123 fake street
            [Telephone] => 1234567890
            [Sex] => yes, please
            [Visited exhibition] => no
        )

    [2] => Array
        (
            [Name] => bob
            [Address] => 123 fake street
            [Telephone] => 1234567890
            [Sex] => yes, please
            [Visited exhibition] => no
        )

    [3] => Array
        (
            [Name] => bob
            [Address] => 123 fake street
            [Telephone] => 1234567890
            [Sex] => yes, please
            [Visited exhibition] => no
        )

    [4] => Array
        (
            [Name] => billy
            [Address] => 456 fake street
            [Telephone] => 2345678901
            [Sex] => no
            [Visited exhibition] => yes
        )

)
person Mike    schedule 04.05.2015
comment
Я не знаю, где использовать trim, не могли бы вы объяснить? - person Anders; 05.05.2015
comment
Вы нигде не ставите trim. Просто откройте файл в режиме добавления, как объясняет остальная часть ответа. - person Mike; 05.05.2015
comment
Я уже использую a на fopen. Удаление PHP_EOL приводит к тому, что данные разных людей будут вставлены в одну строку, но мне нужно, чтобы информация распределялась по многим строкам, по одной для каждого человека. - person Anders; 05.05.2015
comment
Я видел, но не мог полностью понять... Когда вы использовали строку $contents = trim(file_get_contents($file));, вы получали полное содержимое файла с помощью file_get_contents(), удаляли все \n с помощью trim() и приписывали результат $contents, верно? Так почему же вы позже использовали $lines = explode("\n", $contents);? Я понял, что эта строка делит $contents на подстроки, разделенные на \n, и приписывает эту строковую матрицу $lines с помощью explode()... Но зачем использовать параметр \n для explode(), если вы уже удалили все \n с помощью trim()? - person Anders; 10.05.2015
comment
@Anders Причина в том, что trim() удаляет только первый и последний пробельные символы. Итак, если у вас есть {tab}line one{line break}line two{space}{line break}, он преобразует его в line one{line break}line two. Он не удаляет каждый разрыв строки, только если он есть в начале или в конце. И я сделал explode(), чтобы разбить строку на массив, где каждая строка является значением в массиве, чтобы я мог перебирать ее в цикле. - person Mike; 11.05.2015
comment
Я только что нашел еще одну интересную функцию, которая могла бы работать вместо explode и цикла: strtok. Возможно, вы тоже захотите взглянуть на это. - person Mike; 11.05.2015

Проблема в том, как вы читаете файл. Вы тестируете EOF перед чтением из файла. Но feof() не будет истинным, пока вы не попытаетесь прочитать, находясь в конце файла.

Вместо этого вы должны проверить, возвращает ли fgets() строку.

for ($counter = 0; $buffer = fgets($reader); $counter++) {
    $lines[$counter] = explode(" | ", $buffer);
    $combined[$counter] = array_combine($keys, $lines[$counter]);
}

ДЕМО

Для дальнейшего объяснения предположим, что у вас есть файл с одной строкой. Когда $counter равно 0, вы вызываете feof(), и он возвращает false. Затем вы читаете первую строку и добавляете ее к $lines и $combined. Затем вы увеличиваете $counter и возвращаетесь к началу цикла.

Когда $counter становится 1, вы звоните feof(). Это все равно неверно, потому что вы еще не пробовали читать в конце файла. Затем вы пытаетесь прочитать следующую строку, но там нет строки, fgets возвращает false и вы присваиваете это $buffer. explode() обрабатывает это как пустую строку, поэтому вы добавляете пустой массив к $lines и $combined. Затем вы увеличиваете $counter и возвращаетесь к началу цикла.

Затем вы вызываете feof(), и на этот раз он возвращает true, потому что вы пытались прочитать конец файла на предыдущей итерации. Итак, петля заканчивается.

Как вы можете видеть из вышеприведенного, несмотря на то, что в файле всего 1 строка, вы получаете 2 записи в ваших массивах, потому что вы не проверяли EOF, пока не прочитали слишком далеко.

person Barmar    schedule 05.05.2015
comment
Теперь я понимаю. Но изменение цикла, как вы предложили, заставляет его работать очень странно... С этими 3 элементами: ›a | б | с | М | защита ›1 | 2 | 3 | М | 456 ›56 | 78 | 91 | М | 23 › Я получаю такой вывод: Массив ( [0] => Массив ( [Имя] => 1 [Адрес] => 2 [Телефон] => 3 [Пол] => M [Посещенные выставки] => 456 ) [1] =› ) - person Anders; 05.05.2015
comment
Опечатка: $lines[counter] должно быть $lines[$counter] - person Barmar; 05.05.2015
comment
Вам также не хватает закрывающей скобки для array_combine. Как код вообще работает? - person Barmar; 05.05.2015
comment
В коде отсутствуют опечатки и отсутствующие скобки. Они были представлены, когда я перевел код для размещения здесь. - person Anders; 05.05.2015
comment
В комментариях нет форматирования, поэтому я не могу сказать, что вы вводите и выводите. Пожалуйста, обновите вопрос с вашим фактическим кодом, тестовым вводом и выводом. - person Barmar; 05.05.2015
comment
Я не мог понять, что вы хотите, чтобы я добавил... По вопросу уже есть тестовый ввод и вывод. - person Anders; 05.05.2015
comment
Покажите ввод и вывод, которые вы получили, когда пытались реализовать мой ответ. - person Barmar; 05.05.2015

Если вы хотите избавиться от последнего разрыва строки в данных, которые вы извлекли из базы данных ($ res), вы можете использовать следующий фрагмент

for ($i=0; $i <count($res); $i++) {

    // If this is not last item then add items separated by line break
    if($i+1 < count($res)) {
        file_put_contents("file.txt", $res[$i].PHP_EOL, FILE_APPEND);
    }
    // If this is the last item, then don't append the final line break
    else {
        file_put_contents("file.txt", $res[$i], FILE_APPEND);
    }
}
person Robert Sinclair    schedule 29.06.2018