วิธีอ่านไฟล์ที่ไม่มีบรรทัดใหม่ได้อย่างไร


374

ใน Python การโทร

temp = open(filename,'r').readlines()

ผลลัพธ์ในรายการที่แต่ละองค์ประกอบเป็นบรรทัดในไฟล์ มันโง่เล็กน้อย แต่ก็ยัง: readlines()เขียนอักขระขึ้นบรรทัดใหม่ให้แต่ละองค์ประกอบสิ่งที่ฉันไม่ต้องการให้เกิดขึ้น

ฉันจะหลีกเลี่ยงได้อย่างไร


4
ใช้แถบ: [l.strip('\n\r') for l in temp]. rstripหรือแม้กระทั่ง และตั้งแต่ย้ำที่นี่ก็สามารถแทนin open in temp
gorlum0

11
ฉันคงจะดีถ้าใน Python 3 มีค่าที่จะตั้งค่าnewlineอาร์กิวเมนต์ของ open กับ newlines ต่อท้าย chomped
jxramos

ที่เกี่ยวข้อง: stackoverflow.com/questions/275018/…
AMC

คำตอบ:


554

คุณสามารถอ่านไฟล์ทั้งหมดและแยกบรรทัดโดยใช้str.splitlines:

temp = file.read().splitlines()

หรือคุณสามารถตัดบรรทัดใหม่ด้วยมือ:

temp = [line[:-1] for line in file]

หมายเหตุ:โซลูชันล่าสุดนี้ใช้งานได้เฉพาะเมื่อไฟล์ลงท้ายด้วยการขึ้นบรรทัดใหม่มิฉะนั้นบรรทัดสุดท้ายจะสูญเสียอักขระ

สมมติฐานนี้เป็นจริงในกรณีส่วนใหญ่ (โดยเฉพาะอย่างยิ่งสำหรับไฟล์ที่สร้างโดยโปรแกรมแก้ไขข้อความซึ่งมักจะเพิ่มบรรทัดใหม่ที่สิ้นสุดอยู่แล้ว)

หากคุณต้องการหลีกเลี่ยงสิ่งนี้คุณสามารถเพิ่มบรรทัดใหม่ที่ท้ายไฟล์:

with open(the_file, 'r+') as f:
    f.seek(-1, 2)  # go at the end of the file
    if f.read(1) != '\n':
        # add missing newline if not already present
        f.write('\n')
        f.flush()
        f.seek(0)
    lines = [line[:-1] for line in f]

หรือทางเลือกที่ง่ายกว่าคือstripขึ้นบรรทัดใหม่แทน:

[line.rstrip('\n') for line in file]

หรือแม้ว่าจะอ่านไม่ได้

[line[:-(line[-1] == '\n') or len(line)+1] for line in file]

ซึ่งใช้ประโยชน์จากความจริงที่ว่าค่าส่งคืนของorไม่ใช่บูลีน แต่วัตถุที่ถูกประเมินว่าเป็นจริงหรือเท็จ


readlinesวิธีการที่เป็นจริงเทียบเท่ากับ:

def readlines(self):
    lines = []
    for line in iter(self.readline, ''):
        lines.append(line)
    return lines

# or equivalently

def readlines(self):
    lines = []
    while True:
        line = self.readline()
        if not line:
            break
        lines.append(line)
    return lines

ตั้งแต่readline()การขึ้นบรรทัดใหม่ยังreadlines()เก็บมันไว้

หมายเหตุ:สำหรับสมมาตรเพื่อวิธีการไม่ได้เพิ่มสิ้นสุดการขึ้นบรรทัดใหม่เพื่อผลิตสำเนาถูกต้องของในreadlines()writelines()f2.writelines(f.readlines())ff2


1
โปรดทราบว่า[line.rstrip('\n') for line in file]จะลบการติดตามมากกว่าหนึ่ง\nรายการ
Wes Turner

1
เพิ่มเติมเพียงแทนอาจจะเป็น[line[:-(line[-1] == '\n') or len(line)+1] for line in file] [line[:-(line[-1] == '\n') or None] for line in file]
Wes Turner

10
โซลูชันเหล่านี้อ่านไฟล์ทั้งหมดในหน่วยความจำ การเปลี่ยนเครื่องหมายวงเล็บเหลี่ยมของรายการความเข้าใจเป็นวงเล็บทำให้นิพจน์ตัวกำเนิดซึ่งช่วยให้คุณวนซ้ำไฟล์ทีละบรรทัด: for line in (x.strip() for x in f):
Joseph Sheedy

2
@velotron นั่นไม่ใช่ประเด็นของคำถาม / คำตอบ นอกจากนี้โปรดทราบว่าwithปิดไฟล์เมื่อบล็อกถูกยกเลิกซึ่งหมายความว่าคุณไม่สามารถทำได้with open(...) as f: lines = (line for line in f)และใช้linesนอกwithเพราะคุณจะได้รับข้อผิดพลาด I / O คุณสามารถขี้เกียจใช้ genexp แต่คุณต้องกินมันก่อนที่จะปิดไฟล์
Bakuriu

@WesTurner แต่จะไม่มีการขึ้นบรรทัดใหม่มากกว่าหนึ่งบรรทัด ขึ้นบรรทัดใหม่จะเป็นส่วนหนึ่งของบรรทัดว่างถัดไป
นักฟิสิกส์บ้า

38
temp = open(filename,'r').read().split('\n')

14
จะเกิดอะไรขึ้นกับการขึ้น\r\nบรรทัดใหม่ ;)
Wolph

26
Python จัดการการขึ้นบรรทัดใหม่ที่เป็นสากลโดยอัตโนมัติดังนั้นจึง.split('\n')จะแยกอย่างถูกต้องโดยไม่ขึ้นกับระเบียบการขึ้นบรรทัดใหม่ มันจะสำคัญถ้าคุณอ่านไฟล์ในโหมดไบนารีในกรณีนั้นsplitlines()จะจัดการกับบรรทัดใหม่สากลในขณะที่split('\n')ไม่
Bakuriu

7
และมีอยู่เสมอos.linesep:)
Askewchan

1
@ LarsH มันจะช่วยในบางสถานการณ์ใน\r\nตอนท้ายบรรทัดระบบของฉันจะไม่ถูกแปลงเป็น\nไม่ว่าจะอ่านเป็นข้อความหรือไบนารีดังนั้นos.linesepจะทำงานในที่ที่\nไม่ แต่splitlinesเป็นตัวเลือกที่ดีกว่าอย่างชัดเจนในกรณีที่คุณพูดถึงว่าไฟล์ไม่ตรงกับระบบปฏิบัติการ จริง ๆ แล้วฉันพูดถึงมันเป็นส่วนใหญ่ในกรณีที่คนดูการสนทนานี้ไม่ได้ตระหนักถึงการมีอยู่
askewchan

1
@askewchan บางทีคุณอาจกำลังใช้ Python เวอร์ชันล้าสมัย ฉันเชื่อว่าตั้งแต่ Python 3 จะมีการเปิดใช้งานบรรทัดใหม่สากลโดยค่าเริ่มต้นเช่น\r\nจะถูกแปลงเป็นไฟล์ข้อความแม้ในขณะที่คุณใช้งานบน Linux
Arthur Tacca

13

ตัวอย่างอื่น:

อ่านไฟล์ทีละหนึ่งแถว การลบตัวอักษรที่ไม่ต้องการด้วยปลายสายstr.rstrip(chars)

with open(filename, 'r') as fileobj:
    for row in fileobj:
        print( row.rstrip('\n') )

ดูยังstr.strip([chars])และstr.lstrip([chars])

(python> = 2.0)



9

ฉันคิดว่านี่เป็นตัวเลือกที่ดีที่สุด

temp = [line.strip() for line in file.readlines()]

8
โซลูชันนี้ยังลบช่องว่างนำหน้าและต่อท้ายซึ่งไม่ได้มีไว้
Roland Illig

ความเข้าใจนั้นดีมากจริงๆ อย่างน้อยด้วย Python 3 เราสามารถใช้temp = [line.rstrip() for line in file.readlines()]เพื่อรับ @Roland_Illig notes ได้
bballdave025

หากคุณกำลังทำซ้ำทุกบรรทัดทำไมไม่ขี้เกียจ? ด้วย.readlines()คุณจะวนซ้ำไฟล์ทั้งหมดสองครั้งอย่างมีประสิทธิภาพ
AMC

1

ลองสิ่งนี้:

u=open("url.txt","r")  
url=u.read().replace('\n','')  
print(url)  

4
ในขณะที่ข้อมูลโค้ดนี้อาจแก้ไขคำถามรวมถึงคำอธิบายช่วยปรับปรุงคุณภาพของโพสต์ของคุณ จำไว้ว่าคุณกำลังตอบคำถามสำหรับผู้อ่านในอนาคตและคนเหล่านั้นอาจไม่ทราบสาเหตุของการแนะนำรหัสของคุณ โปรดอย่าพยายามทำให้รหัสของคุณแน่นเกินไปด้วยคำอธิบายที่อธิบายเนื่องจากจะช่วยลดความสามารถในการอ่านของทั้งรหัสและคำอธิบาย!
Goodbye StackExchange

ฉันไม่เห็นว่าทำไมทุกคนควรใช้สิ่งนี้กับทางเลือกอื่น
AMC

-1
my_file = open("first_file.txt", "r")
for line in my_file.readlines():
    if line[-1:] == "\n":
        print(line[:-1])
    else:
        print(line)
my_file.close() 

3
โปรดเพิ่มคำอธิบายบางอย่างเพื่อให้เป็นประโยชน์ต่อผู้อื่น
samuellawrentz

คุณควรใช้ตัวจัดการบริบทเพื่อจัดการวัตถุไฟล์และวนซ้ำไฟล์โดยตรง เมื่อใช้.readlines()อย่างนี้คุณจะสามารถวนซ้ำทั้งไฟล์ได้สองครั้งอย่างมีประสิทธิภาพ
AMC

-2
import csv

with open(filename) as f:
    csvreader = csv.reader(f)
    for line in csvreader:
         print(line[0])

2
แต่ถ้าเส้นตรงมีเครื่องหมายจุลภาคอยู่ล่ะ
gilch

-8
def getText():
    file=open("ex1.txt","r");

    names=file.read().split("\n");
    for x,word in enumerate(names):
        if(len(word)>=20):
            return 0;
            print "length of ",word,"is over 20"
            break;
        if(x==20):
            return 0;
            break;
    else:
        return names;


def show(names):
    for word in names:
        len_set=len(set(word))
        print word," ",len_set


for i in range(1):

    names=getText();
    if(names!=0):
        show(names);
    else:
        break;
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.