อ่านและเขียนทับไฟล์ใน Python


109

ตอนนี้ฉันกำลังใช้สิ่งนี้:

f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.close()

แต่ปัญหาคือไฟล์เก่ามีขนาดใหญ่กว่าไฟล์ใหม่ ดังนั้นฉันจึงจบลงด้วยไฟล์ใหม่ที่มีส่วนหนึ่งของไฟล์เก่าอยู่ด้านท้าย

คำตอบ:


180

หากคุณไม่ต้องการปิดและเปิดไฟล์ขึ้นมาใหม่เพื่อหลีกเลี่ยงสภาวะการแข่งขันคุณสามารถทำได้truncate:

f = open(filename, 'r+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.write(text)
f.truncate()
f.close()

ฟังก์ชันนี้จะสะอาดและปลอดภัยยิ่งขึ้นopenเมื่อใช้เป็นตัวจัดการบริบทซึ่งจะปิดตัวจัดการไฟล์แม้ว่าจะมีข้อผิดพลาดเกิดขึ้นก็ตาม!

with open(filename, 'r+') as f:
    text = f.read()
    text = re.sub('foobar', 'bar', text)
    f.seek(0)
    f.write(text)
    f.truncate()

เพื่อความชัดเจนในใจของฉัน - คลิปที่สองของคุณควรมีf.write(text)หลังจากนี้f.truncate()หรือไม่?
volvox

3
@volvox f.write(text)อยู่ก่อนf.truncate()ในรหัสนี้ มันเขียนtextครั้งแรกดังนั้นหลังจาก.write()ที่เคอร์เซอร์ของไฟล์อยู่ในตำแหน่งที่ส่วนท้ายของtext. การดำเนินการตัดทอนไฟล์จะเป็นการลบไบต์ที่เหลืออยู่หลังจากจุดนี้ ในกรณีนี้ผลลัพธ์จะเหมือนกับว่าคุณตัดทอนก่อนเขียน
nosklo

สำหรับไฟล์ที่มีขนาดใหญ่มากการอ่านเนื้อหาของไฟล์ทั้งหมดลงในหน่วยความจำอาจไม่สะดวก ดังนั้นfileinputโมดูลสามารถกลายเป็นวิธีการที่ต้องการได้ เมื่อผ่านไปinplace=1ระบบจะย้ายไฟล์ไปยังตำแหน่งชั่วคราวก่อนจากนั้นจึงเขียนไฟล์ใหม่ไปยังพา ธ ชื่อไฟล์เก่า การดำเนินการย้ายนี้ทำได้อย่างรวดเร็วบนระบบไฟล์ยูนิกซ์เนื่องจากเพียงแค่ย้ายระบบไฟล์inodeไม่ใช่เนื้อหาทั้งหมด จากนั้นคุณสามารถอ่านและประมวลผลทีละบรรทัดเพื่อหลีกเลี่ยงการขยายตัวของหน่วยความจำ :-)
TrinitronX

16

อาจจะง่ายกว่าและจะปิดไฟล์ได้ง่ายกว่าtext = re.sub('foobar', 'bar', text)เปิดใหม่เพื่อเขียน (จึงเป็นการล้างเนื้อหาเก่า) และเขียนข้อความที่อัปเดตลงไป


16

fileinputโมดูลมีinlineโหมดสำหรับการเขียนการเปลี่ยนแปลงไปยังไฟล์ที่คุณกำลังประมวลผลโดยไม่ต้องใช้ไฟล์ชั่วคราว ฯลฯ โมดูลอย่างสุนทรีย์การดำเนินงานร่วมกันของบ่วงผ่านสายในรายการของไฟล์ผ่านทางวัตถุที่โปร่งใสติดตามชื่อไฟล์ที่ หมายเลขบรรทัด ฯลฯ หากคุณต้องการตรวจสอบภายในลูป

import fileinput
for line in fileinput.FileInput("file",inplace=1):
    if "foobar" in line:
         line=line.replace("foobar","bar")
    print line

0

จริงๆแล้วคุณสามารถดูคลาสนี้ที่ฉันสร้างขึ้นซึ่งใช้งานไฟล์พื้นฐาน วิธีการเขียนจะเขียนทับและผนวกข้อมูลเก่าไว้

class IO:
    def read(self, filename):
        toRead = open(filename, "rb")

        out = toRead.read()
        toRead.close()
        
        return out
    
    def write(self, filename, data):
        toWrite = open(filename, "wb")

        out = toWrite.write(data)
        toWrite.close()

    def append(self, filename, data):
        append = self.read(filename)
        self.write(filename, append+data)
        

-2

ลองเขียนในไฟล์ใหม่ ..

f = open(filename, 'r+')
f2= open(filename2,'a+')
text = f.read()
text = re.sub('foobar', 'bar', text)
f.seek(0)
f.close()
f2.write(text)
fw.close()
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.