PHP:如何从文本文件中删除最后一个换行符?

3
在一项学校作业中,我使用 PHP 为我城市的虚构太空博物馆建立了一个网站。它具有数据包含和数据查询系统,但我在查询方面遇到了问题:如何删除文件中的最后一行换行符?

数据包含

在网站的限制区域中,我有一个具有5个字段(姓名、地址、电话号码、性别和参观展览)的 HTML5 表单,通过POST方法将数据发送给 PHP 中的一个函数,并使用 fwrite 命令将其写入给定的文本文件中:

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

正如您所见,它在一个文本文件中写入了表单中输入的数据,以及一个换行符。指针是fopen用于打开我需要处理的文件的变量。输出示例:

Márcio Aguiar | Belmiro Braga Street | 1234-5678 | M | Planets of Solar System
Joana Tobias | Santos Dummont Avenue | 8765-4321 | F | Black Holes, Satellites

数据查询

然后是一个查询系统。它有一个循环,直到文件结束为止。在这个循环中,有一个名为$buffer的变量,每次获取txt文件的一行内容。然后将其explode以创建一个名为$lines[$counter]的数组。为了漂亮地打印它,我使用了一个array_combine,在其中将另一个数组($keys)中的字段名称与$lines[$counter]中写入的值结合起来,并将其赋值给$combined[$counter]。然后循环结束,我在<pre></pre>中使用print_r来查看写入$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行

3个回答

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
        )

)

我不知道在哪里使用 trim,你能解释一下吗? - user4863385
你没有使用 trim。只需按照答案中的说明以追加模式打开文件即可。 - Mike
我已经在fopen上使用了a。删除PHP_EOL会使不同人的数据都插入到一行中,但我需要将信息分布在许多行上,每个人占一行。 - user4863385
我看到了,但是没有完全理解... 当你使用了$contents = trim(file_get_contents($file));这行代码时,你通过使用file_get_contents()获取了文件的全部内容,然后通过使用trim()去除了所有的\n,并将结果赋值给了$contents,对吗? 那么为什么之后你又使用了$lines = explode("\n", $contents);这行代码呢?我理解这行代码是将$contents按照\n分割成子字符串,并通过explode()将这个字符串矩阵赋值给了$lines... 但是既然你已经使用trim()去除了所有的\n,为什么还要在explode()中使用参数\n呢? - user4863385
@Anders 的原因是因为 trim() 只会删除第一个和最后一个空格字符。所以如果你有 {tab}line one{line break}line two{space}{line break},它会将其转换为 line one{line break}line two。它不会去除 每个 换行符,只有在开头或结尾有换行符时才会去除。我使用 explode() 将字符串拆分成一个数组,其中每一行都是数组中的一个值,这样我就可以循环遍历它了。 - Mike
我刚刚发现了另一个有趣的函数,可以代替explode和循环:strtok。你也可以看看这个。 - Mike

1
问题在于您读取文件的方式。您在读取文件之前测试了EOF,但是只有当您在文件末尾尝试读取时,feof()才会为真。
相反,您应该测试fgets()是否返回一行。
for ($counter = 0; $buffer = fgets($reader); $counter++) {
    $lines[$counter] = explode(" | ", $buffer);
    $combined[$counter] = array_combine($keys, $lines[$counter]);
}

DEMO

进一步解释,假设你有一个只有一行的文件。当$counter0时,调用feof()函数,它返回false。然后你读取第一行,并将其添加到$lines$combined中。然后你增加$counter并回到循环的开头。

$counter1时,调用feof()函数。它仍然不是真的,因为你还没有尝试在文件末尾读取。然后你尝试读取下一行,但那里没有行了,fgets函数返回false,你将其赋给$buffer。这被explode()函数视为空字符串,所以你向$lines$combined添加了一个空数组。然后你增加$counter并回到循环的开头。

然后你调用 feof(),这一次它返回了 true,因为在上一次迭代中你试图在文件末尾读取。所以循环结束。

从上面可以看出,即使文件只有1行,由于你没有在读取太多之前测试EOF,所以最终会得到2个数组条目。


我现在明白了。但是按照你建议的更改循环后,它的工作方式变得非常奇怪...使用这3个项目:
a | b | c | M | def 1 | 2 | 3 | M | 456 56 | 78 | 91 | M | 23
我得到了这个输出: 数组 ( [0] => 数组 ( [姓名] => 1 [地址] => 2 [电话] => 3 [性别] => M [参观展览] => 456 ) [1] => )
- user4863385
笔误:$lines[counter] 应该为 $lines[$counter] - Barmar
你还缺少了array_combine的右括号。这段代码怎么能运行呢? - Barmar
代码中不存在打字错误和缺少括号。这些是我在翻译代码发布到这里时引入的。 - user4863385
评论中没有格式,所以我无法确定您的输入和输出是什么。请使用实际代码、测试输入和输出更新问题。 - Barmar
显示剩余2条评论

0
如果您想要从数据库中获取的数据($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);
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接