อักขระตัวสุดท้ายในไฟล์คืออะไร


19

ฉันเพิ่งอ่านคำตอบของ "การลบอักขระบรรทัดใหม่ที่ท้ายไฟล์" และทุกคนบอกว่าจะลบอักขระตัวสุดท้าย คำถามของฉันคือตัวละครสุดท้ายไม่ใช่ตัวละครสุดท้ายใช่ไหม


11
EOF ไม่ได้เป็นตัวละคร
Soren Bjornstad

1
@SorenBjornstad ฉันต้องการที่จะเพิ่มว่าเมื่อมีการขึ้นบรรทัดใหม่ในตอนท้ายของไฟล์ข้อความ Unix มันอยู่ที่นั่นเพราะมันจะยุติบรรทัดสุดท้าย ไฟล์ข้อความที่ว่างเปล่าไม่มีการขึ้นบรรทัดใหม่ในตอนท้าย: มันเป็นลำดับของอักขระศูนย์
Kaz

3
หากต้องการความคล่องแคล่วเล็กน้อย CPM และ DOS ใช้ ^ Z เป็นอักขระ EOF และบางครั้งคุณอาจพบไฟล์ที่ลงท้ายด้วย ^ Z
Edward Falk

คำตอบ:


13

ไฟล์ไม่ได้ลงท้ายด้วยอักขระ End of File เนื่องจากคำตอบก่อนหน้านี้ระบุไว้อย่างถูกต้อง แต่ฉันคิดว่าคำตอบและความคิดเห็นมีความไม่ถูกต้องบางอย่างที่ชี้ให้เห็น:

  • ชุดอักขระ ASCII ไม่มีอักขระ EOF ที่แน่นอน มีอักขระควบคุม "สิ้นสุด" หลายตัว: สิ้นสุดข้อความ (3), สิ้นสุดการส่ง (4), สิ้นสุดการส่งบล็อก (23), สิ้นสุดกลาง (25) ตัวแยกไฟล์ (28) อาจใกล้เคียงกับอักขระ EOF มากที่สุด รหัส 26 คือ "ทดแทน" ไม่ใช่ EOF

  • Ctrl- Dเชื่อมโยงกับอินพุตเทอร์มินัลเท่านั้น ยกตัวอย่างเช่นคำสั่ง cat filea fileb filec > outfileไม่เกี่ยวข้องกับ-Ctrl Dโดยวิธีการที่คุณสามารถเปลี่ยนตัวอักษร EOF terminal เพื่อสิ่งอื่นมากกว่าCtrl- Dการใช้sttyคำสั่ง

  • การพูดอย่างเคร่งครัดCtrl- D(หรือสิ่งที่คุณเปลี่ยนไป) ไม่ใช่รหัสคีย์ EOF สิ่งที่ทำให้การreadเรียกระบบกลับด้วยอินพุตที่มีอยู่เช่นเดียวกับการกดส่งคืนทำให้การเรียกระบบการอ่านส่งคืนบรรทัดของอักขระไปยังผู้โทร โดยการประชุมค่าส่งกลับเป็นศูนย์จากการเรียกระบบการอ่าน (เช่นการอ่านตัวอักษรศูนย์) สัญญาณสิ้นสุดของสภาพไฟล์ อย่างไรก็ตามไฟล์อินพุตจะไม่ปิดโดยอัตโนมัติและหากอินพุตมาจากเทอร์มินัลจะไม่ถูกทำให้อยู่ในสถานะ "สิ้นสุดไฟล์" คุณสามารถเขียนโปรแกรมที่อ่านต่อจากเทอร์มินัลแม้หลังจาก "สิ้นสุดไฟล์" และการเรียกเพื่ออ่านสามารถส่งคืนค่าที่ไม่ใช่ศูนย์สำหรับบรรทัดอินพุตถัดไป

  • การเปรียบเทียบระหว่างตัวอักษร eof และ eol สามารถดูได้ว่าCtrl- Dถูกกดหรือไม่เมื่ออินพุตบางส่วนถูกเขียนบนบรรทัดแล้ว ตัวอย่างเช่นถ้าคุณเขียน "abc" และกดCtrl- Dการเรียก read จะส่งคืนเวลานี้ด้วยค่าส่งคืน 3 และเก็บ "abc" ไว้ในบัฟเฟอร์ที่ส่งผ่านเป็นอาร์กิวเมนต์ เนื่องจากการอ่านไม่ส่งคืน 0 นี่จึงไม่ถูกตีความว่าเป็นเงื่อนไข EOF ตามแบบแผนด้านบน ในทำนองเดียวกันการกดปุ่มย้อนกลับเพื่อทำให้การโทรกลับอ่านด้วยสายอินพุตทั้งหมด (รวมถึงบรรทัดใหม่) คุณสามารถทดลองนี้ด้วยcatคำสั่ง: เขียนตัวอักษรบางอย่างเกี่ยวกับเส้นและการกด-Ctrl Dคุณจะเห็นตัวละครดังก้องกลับมาหาคุณและcatรอการป้อนข้อมูลเพิ่มเติม

  • ทั้งหมดข้างต้นใช้เฉพาะเมื่อเทอร์มินัลอยู่ในโหมด "สุก" ซึ่งตรงข้ามกับโหมด "ดิบ" ซึ่งการประมวลผลอินพุตบรรทัดจะถูกย่อให้เล็กสุด ในโหมด raw อักขระ Ctrl-D จะถูกส่งไปยังบัฟเฟอร์อินพุตจริง ๆ


19

อักขระควบคุม ASCII มีคำจำกัดความจากปี 1960 (จริง ๆ แล้วนำหน้าสิ่งที่คุณอาจพิจารณาถึงเครือข่าย ) ไม่ใช่ว่าจะมีการใช้อักขระควบคุมทั้งหมดตามวิธีที่กำหนดไว้สำหรับอุปกรณ์โทรคมนาคมในตอนนั้น

บนระบบที่เหมือน Unix ไม่จำเป็นต้องมีEOFตัวอักษร ไม่มีการใช้ ระบบสามารถบอกแอปพลิเคชันว่ามีกี่ไบต์ในไฟล์:

  • ในบางระบบอื่น ๆ (เห็นใน VMS, DOS, Windows) ตัวควบคุม -Z อาจทำหน้าที่เป็นตัวสิ้นสุดไฟล์เพราะในรุ่นเก่าระบบไม่สามารถบอกบางแอปพลิเคชันได้ว่ามีกี่ไบต์ในไฟล์

    ในกรณีของ VMS ข้อ จำกัด เกิดจากการทำงานของ C runtime แอปพลิเคชันภาษาแอสเซมบลี (และสามารถทำได้) รับขนาดไฟล์ที่ถูกต้อง

  • ระบบ Unix ในเชลล์ใช้ control-D เพื่อบอกแอ็พพลิเคชันว่าถึงจุดสิ้นสุดของอินพุต (ไฟล์) แล้ว แต่ control-D ไม่ได้เก็บไว้ในไฟล์

ใน C EOFถูกสร้างขึ้นโดยมีจุดประสงค์-1เพื่อระบุว่าไม่ใช่อักขระที่ถูกต้อง I / O มาตรฐานจะส่งกลับEOFเมื่อตรวจพบเงื่อนไขการสิ้นสุดไฟล์ - ไม่ใช่อักขระพิเศษ

อย่างไรก็ตามไฟล์ไม่จำเป็นต้องลงท้ายด้วยอักขระขึ้นบรรทัดใหม่ (ASCII line-feed) เครื่องมือแก้ไขข้อความสามารถรับมือกับไฟล์ที่เป็นข้อความที่พิมพ์ได้ทั้งหมด แต่ไม่มีบรรทัดใหม่ต่อท้าย


8
POSIX กำหนดไฟล์ข้อความเป็นไฟล์ที่มีลำดับของบรรทัดและเปิดแต่ละบรรทัดเป็นลำดับของอักขระที่ไม่ใช่บรรทัดใหม่ตามด้วยบรรทัดใหม่หนึ่งบรรทัด ดังนั้นไฟล์ที่ลงท้ายด้วยอะไรก็ได้ แต่ 0x0A ไม่ใช่ไฟล์ข้อความที่สอดคล้อง
Damian Yerrick

2
ฉันตระหนักถึงสิ่งนั้นซึ่งเป็นเหตุให้ฉันชี้ให้เห็นว่าเครื่องมือแก้ไขข้อความใช้งานได้ (ไฟล์ไบนารีไม่มีข้อ จำกัด ดังกล่าว)
Thomas Dickey

เป็นเรื่องที่น่าสังเกตว่าไฟล์ที่ตั้งใจจะจัดการเป็นข้อความที่ไม่มีบรรทัดใหม่ต่อท้ายยังคงเป็นรูปแบบที่ไม่ดี (แม้ว่าโปรแกรมแก้ไขข้อความทั่วไปจะถูกเข้ารหัสเพื่อชดเชยไฟล์ดังกล่าว) อย่างน้อยถ้าคุณต้องการให้มันเป็นจริง เป็นมิตรกับผู้ใช้อย่างกว้างขวาง / ใช้งานร่วมกันได้เนื่องจากการขาดบรรทัดใหม่ต่อท้ายสามารถเพิ่มความยากลำบากเพิ่มเติมในสถานการณ์ต่าง ๆ (การต่อ / พิมพ์ไฟล์ข้อความหลายไฟล์แยกวิเคราะห์ด้วยเครื่องมือบรรทัดคำสั่งทั่วไปเครื่องมือแก้ไขขั้นต่ำสุดเช่นbusybox's viเป็นต้น)
mtraceur

(1) ก่อน VMS RT-11 RSX-11 TOPS-10 มีระบบไฟล์ที่แม่นยำสำหรับบล็อกและต้องการอักขระ EOF เท่านั้น CP / M เช่นกันซึ่งเห็นได้ชัดว่าได้คัดลอกมาจาก DEC และในทางกลับกันก็ถูกคัดลอกโดย MS-DOS ต้นแล้วจึงส่งต่อไปยัง Windows (2) ใน Unix มันคือไดรเวอร์ tty ไม่ใช่ shell ดังอธิบายในรายละเอียดโดย JohanM แม้ว่าผู้คนมักใช้ shells บนอุปกรณ์ tty
dave_thompson_085

แน่นอน - DEC กลับมาแล้ว (และโปรดทราบว่าฉันพูดถึงรุ่นเก่ากว่า) ไม่ว่าจะเป็นจุดเริ่มต้นของคุณลักษณะ CP / M จะเป็นหัวข้อที่น่าสนใจในการสำรวจ (ไม่ใช่ที่นี่); ฉันพูดถึงกรณีเหล่านั้นเพื่อให้พื้นหลังบางอย่างกับทางเลือก
Thomas Dickey

7

EOF ไม่ใช่ตัวละคร มันเป็นสถานะที่บ่งบอกว่าไม่มีตัวละครที่จะอ่านจากกระแสไฟล์ เมื่อคุณป้อนคำสั่ง EOF จากเทอร์มินัลคุณกำลังส่งสัญญาณระบบปฏิบัติการเพื่อปิดอินพุตสตรีมไม่ใส่อักขระพิเศษ


1
ใช่ แต่ใน ASCII ตาราง EOF คือ 26 ดังนั้นฉันคิดว่าไบต์สุดท้ายคือการแทนเลขฐานสองของ 26 ดังนั้นโปรแกรมที่อ่านอินพุตจะรู้ได้อย่างไรว่ามันจบลงที่ใด?
sworwitz

ASCII มีไว้สำหรับการส่งข้อมูลผ่านเครือข่าย ในกรณีนี้คุณต้องใช้อักขระ EOF (ASCII มีรหัสควบคุมจำนวนมากเช่นกันไม่ใช่ทุกอย่างที่พิมพ์ได้) ในกรณีของสตรีมไฟล์ขนาดของไฟล์เป็นที่รู้จักกันแล้วผ่านระบบไฟล์เพื่อให้ระบบปฏิบัติการสามารถบอกได้เมื่อไม่มีข้อมูลเพิ่มเติมให้อ่าน
มูนีร์

@sworwitz: สำหรับ C ฟังก์ชั่นการอ่านอินพุตที่ส่งกลับอักขระต่อการโทรจะส่งคืนค่า int (โดยทั่วไปคือหมายเลข 32 บิต แต่ต้องเป็น 16 บิตขั้นต่ำ) ไม่ใช่อักขระ สัญญาณฟังก์ชั่นและ EOF โดยส่งกลับ -1 (0xffffffff) ซึ่งไม่ใช่ค่า 8 บิตที่ถูกต้องดังนั้นมันจะไม่สับสนกับอักขระ ASCII ใด ๆ แม้แต่ 0xff ฟังก์ชั่นที่คืนค่าสตริงจะส่งคืนความยาวของข้อมูลที่อ่าน ความยาวนี้อาจใช้เพื่อส่งสัญญาณข้อมูลหรือจุดสิ้นสุดของข้อมูล (อีกครั้งความยาวสามารถเป็น -1) ในที่สุดนอกจากนี้ยังมีฟังก์ชั่นที่คุณสามารถโทรหาที่จะบอกคุณถ้ากระแสได้ถึงปลาย
slebetman

โอเคขอบคุณ! ดังนั้นเมื่ออยู่ในทุบตีฉันกด Ctrl + d ฉันให้ในการป้อนอักขระ ASCII ใช่มั้ย?
sworwitz

@sworwitz ไม่ตรง ก่อนที่bashจะถึงมือของมันกับอินพุตมันจะถูกนวดโดยไดรเวอร์ TTY ไดรเวอร์นี้ดัก Ctrl-D และส่ง EOF ไปที่bash (โดยที่ EOF ไม่ใช่ตัวอักษร แต่เป็นสถานะไฟล์พิเศษ)
Stig Hemmer
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.