PHP: วิธีลบตัวแบ่งบรรทัดสุดท้ายออกจากไฟล์ข้อความ?

ในงานของโรงเรียน ฉันสร้างเว็บไซต์สำหรับพิพิธภัณฑ์อวกาศสมมติในเมืองของฉันโดยใช้ PHP มีระบบ Data Inclusion และ Data Consultation แต่ฉันมีปัญหาในการให้คำปรึกษาที่ต้องการทราบวิธีแก้ปัญหา: จะลบตัวแบ่งบรรทัดสุดท้ายออกจากไฟล์ได้อย่างไร?

การรวมข้อมูล

ในพื้นที่จำกัดของไซต์ ฉันมีแบบฟอร์ม HTML5 พร้อม 5 ฟิลด์ (ชื่อ ที่อยู่ หมายเลขโทรศัพท์ เพศ และนิทรรศการที่เยี่ยมชม) ซึ่งส่งข้อมูลโดยวิธี POST ไปยังฟังก์ชันใน PHP ที่เขียนลงในไฟล์ txt ที่กำหนด โดยใช้คำสั่ง fwrite:

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

อย่างที่คุณเห็น ข้อมูลที่ป้อนในแบบฟอร์มจะเขียนเป็นไฟล์ txt พร้อมการขึ้นบรรทัดใหม่ ตัวชี้คือตัวแปรที่ใช้โดย fopen เพื่อเปิดไฟล์ที่ฉันต้องใช้งาน ตัวอย่างผลลัพธ์:

มาร์ซิโอ อากีอาร์ | ถนนเบลมิโร บรากา | 1234-5678 | เอ็ม | ดาวเคราะห์ในระบบสุริยะ
Joana Tobias | ซานโตส ดัมมอนต์ อเวนิว | 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() ลบ \ns ทั้งหมดออกโดยใช้ trim() และถือว่าผลลัพธ์เป็น $contents ใช่ไหม แล้วทำไมคุณถึงใช้ $lines = explode("\n", $contents); ในภายหลัง? ฉันเข้าใจว่าบรรทัดนี้หาร $contents ในสตริงย่อยหารด้วย \ns และกำหนดคุณลักษณะของเมทริกซ์สตริงนี้เป็น $lines โดยใช้ explode()... แต่เหตุใดจึงใช้พารามิเตอร์ \n บน explode() หากคุณลบ \ns ทั้งหมดโดยใช้ 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 | ข | ค | เอ็ม | def ›1 | 2 | 3 | เอ็ม | 456 ›56 | 78 | 91 | เอ็ม | 23 › ฉันได้รับผลลัพธ์นี้: Array ( [0] =› Array ( [ชื่อ] =› 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

ในกรณีที่คุณต้องการกำจัดตัวแบ่งบรรทัดสุดท้ายในข้อมูลที่คุณดึงมาจาก db ($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