@Ani posting lainnya adalah duplikat dari Memasukkan Baris di Posisi Tertentu dari File Teks dan tentu saja ada jawaban yang jelas terdiri di sini, Mengapa tidak menambahkan jawaban Anda di sini alih-alih dengan cara lain? Jawaban yang diterima bukan persyaratan untuk pertanyaan yang bagus.
Bhargav Rao
@BhargavRao Vote ditarik. Saya seharusnya menemukan duplikat itu!
Ani Menon
Jawaban:
134
Sayangnya tidak ada cara untuk menyisipkan ke tengah file tanpa menulis ulang. Seperti yang ditunjukkan oleh poster sebelumnya, Anda dapat menambahkan file atau menimpa sebagian dari file tersebut menggunakan seek tetapi jika Anda ingin menambahkan barang di awal atau tengah, Anda harus menulis ulang.
Ini adalah masalah sistem operasi, bukan masalah Python. Itu sama dalam semua bahasa.
Apa yang biasanya saya lakukan adalah membaca dari file, membuat modifikasi dan menuliskannya ke file baru bernama myfile.txt.tmp atau sesuatu seperti itu. Ini lebih baik daripada membaca seluruh file ke dalam memori karena file tersebut mungkin terlalu besar untuk itu. Setelah file sementara selesai, saya ganti namanya sama dengan file aslinya.
Ini adalah cara yang baik dan aman untuk melakukannya karena jika file tulis macet atau dibatalkan karena alasan apa pun, Anda masih memiliki file asli Anda yang belum tersentuh.
Apakah alat unix seperti awk / sed melakukan sesuatu yang serupa dalam kode mereka?
Manish Gill
Tidak benar bahwa ini sama di semua bahasa. Dalam ActionScript: fileStream.openAsync (nama file, FileMode.UPDATE); Lalu saya bisa pergi ke mana saja dalam file yang saya inginkan dan mengubah apa pun.
AndrewBenjamin
2
@AndrewBenjamin. Apakah Anda tahu panggilan sistem apa yang dibuat ActionScript? Apakah ada kemungkinan openAsync membaca file dan menulis yang baru setelah panggilan?
AlexLordThorsen
@Rawrgulmuffins saya tidak. Namun, saya tahu itu tidak membaca seluruh file ke dalam memori, karena saya telah menggunakannya untuk menangani ukuran file beberapa GB. Saya menduga itu sama dengan menulis dengan C # streamwriter. Saya melihat python sebagai alat untuk melakukan hal-hal kecil dengan cepat, daripada pengembangan skala besar dan manipulasi file.
AndrewBenjamin
4
@AndrewBenjamin, pengguna tidak bertanya tentang mencari-cari dalam file dan mengubahnya (setiap bahasa yang saya tahu bisa melakukan itu); ia bertanya tentang memasukkan teks, yang berbeda dari sekadar mengubah / menimpa apa yang sudah ada dalam file. Mungkin dalam aplikasi praktis itu berbeda, tetapi tidak ada yang dapat saya temukan di API ActionScript menunjukkan bahwa ia berperilaku berbeda dari bahasa lain dalam hal ini.
eestrada
104
Tergantung pada apa yang ingin Anda lakukan. Untuk menambahkan Anda dapat membukanya dengan "a":
with open("foo.txt","a")as f:
f.write("new line\n")
Jika Anda ingin preprend sesuatu yang harus Anda baca dari file terlebih dahulu:
with open("foo.txt","r+")as f:
old = f.read()# read everything in the file
f.seek(0)# rewind
f.write("new line\n"+ old)# write the new line before
Hanya tambahan kecil, untuk menggunakan withpernyataan dalam Python 2.5 Anda perlu menambahkan "dari impor with_statement" di masa depan . Selain itu, membuka file dengan withpernyataan jelas lebih mudah dibaca dan lebih rentan kesalahan daripada penutupan manual.
Alexander Kojevnikov
2
Anda mungkin mempertimbangkan fileinputlib pembantu dengan menangani rutin buka / baca / modifikasi / tulis / ganti yang kotor saat menggunakan inline=Truearg. Contoh di sini: stackoverflow.com/a/2363893/47390
mikegreenberg
3
Hanya saja, jangan lupa untuk menutup file. f.Close()
D.Rosado
5
Ini bukan gaya yang saya gunakan, D.Rosado, tetapi ketika menggunakan gaya with, saya tidak berpikir Anda harus menutupnya secara manual. Dengan melacak sumber daya yang dibuatnya.
Chris
4
Anda tidak perlu menutup file secara manual. Itulah inti menggunakan "dengan" di sini. (Yah, sebenarnya, Python melakukan ini segera setelah objek file dikumpulkan sampah, yang dalam CPython terjadi ketika nama terikat padanya keluar dari ruang lingkup ... tetapi implementasi lainnya tidak, dan CPython mungkin berhenti melakukannya suatu hari , jadi "dengan" disarankan)
Jürgen A. Erhard
71
The fileinputmodul Python perpustakaan standar akan menulis ulang inplace berkas jika Anda menggunakan inplace = 1 parameter:
import sys
import fileinput
# replace all occurrences of 'sit' with 'SIT' and insert a line after the 5thfor i, line in enumerate(fileinput.input('lorem_ipsum.txt', inplace=1)):
sys.stdout.write(line.replace('sit','SIT'))# replace 'sit' and writeif i ==4: sys.stdout.write('\n')# write a blank line after the 5th line
Bagaimana ini diharapkan bekerja di python3? Saya baru saja mem-porting aplikasi yang memiliki beberapa kode seperti ini dari python ke python3 dan saya tidak bisa menjalankannya sama sekali. Variabel 'line' adalah tipe byte, saya mencoba mendekodekannya menjadi unicode dan kemudian memodifikasinya lalu mengkodekannya kembali ke byte tetapi itu tidak akan berfungsi dengan baik. Itu menimbulkan beberapa pengecualian yang tidak bisa saya ingat dari atas kepala saya. Apakah orang yang menggunakan fileinput inplace = 1 di python3 berhasil?
Tapi tidak masalah karena Anda mengujinya terlebih dahulu pada file yang tidak penting, kan?
Paula Livingstone
33
Menulis ulang file di tempat sering dilakukan dengan menyimpan salinan lama dengan nama yang dimodifikasi. Orang Unix menambahkan ~untuk menandai yang lama. Orang-orang Windows melakukan semua hal - menambahkan .bak atau .old - atau mengganti nama file seluruhnya atau meletakkan ~ di bagian depan nama.
import shutil
shutil.move( afile, afile+"~")
destination= open( aFile,"w")
source= open( aFile+"~","r")for line in source:
destination.write( line )if<some condition>:
destination.write(>some additional line>+"\n")
source.close()
destination.close()
Alih-alih shutil, Anda dapat menggunakan yang berikut ini.
Kelihatan bagus. Ingin tahu apakah .readlines () lebih baik daripada iterasi sumbernya?
bozdoz
2
@ bozdoz: iterasi lebih baik karena readlines membaca seluruh file. Tidak bagus untuk file besar. Tentu saja, ini mengandaikan Anda dapat melakukan modifikasi dengan cara yang terlokalisasi. Terkadang Anda tidak bisa, atau kode Anda menjadi jauh lebih rumit.
Jürgen A. Erhard
@ S.Lott: os.rename(aFile, aFile + "~")akan mengubah nama file sumber, bukan membuat salinan.
Patapoom
14
Modul mmap Python akan memungkinkan Anda untuk memasukkan ke dalam file. Sampel berikut menunjukkan bagaimana hal itu dapat dilakukan di Unix (Windows mmap mungkin berbeda). Perhatikan bahwa ini tidak menangani semua kondisi kesalahan dan Anda mungkin merusak atau kehilangan file asli. Juga, ini tidak akan menangani string unicode.
import os
from mmap import mmap
def insert(filename, str, pos):if len(str)<1:# nothing to insertreturn
f = open(filename,'r+')
m = mmap(f.fileno(), os.path.getsize(filename))
origSize = m.size()# or this could be an errorif pos > origSize:
pos = origSize
elif pos <0:
pos =0
m.resize(origSize + len(str))
m[pos+len(str):]= m[pos:origSize]
m[pos:pos+len(str)]= str
m.close()
f.close()
Dimungkinkan juga untuk melakukan ini tanpa mmap dengan file dibuka dalam mode 'r +', tetapi lebih tidak nyaman dan kurang efisien karena Anda harus membaca dan menyimpan sementara file dari posisi penyisipan ke EOF - yang mungkin menjadi besar.
Seperti yang disebutkan oleh Adam Anda harus mempertimbangkan keterbatasan sistem Anda sebelum Anda dapat memutuskan pendekatan apakah Anda memiliki cukup memori untuk membaca semuanya ke dalam memori, ganti bagian-bagiannya dan tulis ulang.
Jika Anda berurusan dengan file kecil atau tidak memiliki masalah memori ini dapat membantu:
Opsi 1)
Baca seluruh file ke dalam memori, lakukan substitusi regex pada seluruh atau sebagian dari baris dan ganti dengan garis itu ditambah garis tambahan. Anda harus memastikan bahwa 'garis tengah' unik dalam file atau jika Anda memiliki cap waktu di setiap baris, ini harus cukup andal.
# open file with r+b (allow write and binary mode)
f = open("file.log",'r+b')# read entire content of file into memory
f_content = f.read()# basically match middle line and replace it with itself and the extra line
f_content = re.sub(r'(middle line)', r'\1\nnew line', f_content)# return pointer to top of file so we can re-write the content with replaced string
f.seek(0)# clear file content
f.truncate()# re-write the content with the updated content
f.write(f_content)# close file
f.close()
Opsi 2)
Mencari tahu garis tengah, dan menggantinya dengan garis itu ditambah garis tambahan.
# open file with r+b (allow write and binary mode)
f = open("file.log",'r+b')# get array of lines
f_content = f.readlines()# get middle line
middle_line = len(f_content)/2# overwrite middle line
f_content[middle_line]+="\nnew line"# return pointer to top of file so we can re-write the content with replaced string
f.seek(0)# clear file content
f.truncate()# re-write the content with the updated content
f.write(''.join(f_content))# close file
f.close()
Jawaban:
Sayangnya tidak ada cara untuk menyisipkan ke tengah file tanpa menulis ulang. Seperti yang ditunjukkan oleh poster sebelumnya, Anda dapat menambahkan file atau menimpa sebagian dari file tersebut menggunakan seek tetapi jika Anda ingin menambahkan barang di awal atau tengah, Anda harus menulis ulang.
Ini adalah masalah sistem operasi, bukan masalah Python. Itu sama dalam semua bahasa.
Apa yang biasanya saya lakukan adalah membaca dari file, membuat modifikasi dan menuliskannya ke file baru bernama myfile.txt.tmp atau sesuatu seperti itu. Ini lebih baik daripada membaca seluruh file ke dalam memori karena file tersebut mungkin terlalu besar untuk itu. Setelah file sementara selesai, saya ganti namanya sama dengan file aslinya.
Ini adalah cara yang baik dan aman untuk melakukannya karena jika file tulis macet atau dibatalkan karena alasan apa pun, Anda masih memiliki file asli Anda yang belum tersentuh.
sumber
Tergantung pada apa yang ingin Anda lakukan. Untuk menambahkan Anda dapat membukanya dengan "a":
Jika Anda ingin preprend sesuatu yang harus Anda baca dari file terlebih dahulu:
sumber
with
pernyataan dalam Python 2.5 Anda perlu menambahkan "dari impor with_statement" di masa depan . Selain itu, membuka file denganwith
pernyataan jelas lebih mudah dibaca dan lebih rentan kesalahan daripada penutupan manual.fileinput
lib pembantu dengan menangani rutin buka / baca / modifikasi / tulis / ganti yang kotor saat menggunakaninline=True
arg. Contoh di sini: stackoverflow.com/a/2363893/47390f.Close()
The
fileinput
modul Python perpustakaan standar akan menulis ulang inplace berkas jika Anda menggunakan inplace = 1 parameter:sumber
Menulis ulang file di tempat sering dilakukan dengan menyimpan salinan lama dengan nama yang dimodifikasi. Orang Unix menambahkan
~
untuk menandai yang lama. Orang-orang Windows melakukan semua hal - menambahkan .bak atau .old - atau mengganti nama file seluruhnya atau meletakkan ~ di bagian depan nama.Alih-alih
shutil
, Anda dapat menggunakan yang berikut ini.sumber
os.rename(aFile, aFile + "~")
akan mengubah nama file sumber, bukan membuat salinan.Modul mmap Python akan memungkinkan Anda untuk memasukkan ke dalam file. Sampel berikut menunjukkan bagaimana hal itu dapat dilakukan di Unix (Windows mmap mungkin berbeda). Perhatikan bahwa ini tidak menangani semua kondisi kesalahan dan Anda mungkin merusak atau kehilangan file asli. Juga, ini tidak akan menangani string unicode.
Dimungkinkan juga untuk melakukan ini tanpa mmap dengan file dibuka dalam mode 'r +', tetapi lebih tidak nyaman dan kurang efisien karena Anda harus membaca dan menyimpan sementara file dari posisi penyisipan ke EOF - yang mungkin menjadi besar.
sumber
Seperti yang disebutkan oleh Adam Anda harus mempertimbangkan keterbatasan sistem Anda sebelum Anda dapat memutuskan pendekatan apakah Anda memiliki cukup memori untuk membaca semuanya ke dalam memori, ganti bagian-bagiannya dan tulis ulang.
Jika Anda berurusan dengan file kecil atau tidak memiliki masalah memori ini dapat membantu:
Opsi 1) Baca seluruh file ke dalam memori, lakukan substitusi regex pada seluruh atau sebagian dari baris dan ganti dengan garis itu ditambah garis tambahan. Anda harus memastikan bahwa 'garis tengah' unik dalam file atau jika Anda memiliki cap waktu di setiap baris, ini harus cukup andal.
Opsi 2) Mencari tahu garis tengah, dan menggantinya dengan garis itu ditambah garis tambahan.
sumber
Menulis kelas kecil untuk melakukan ini dengan bersih.
Maka Anda dapat menggunakannya dengan cara ini:
sumber
Jika Anda tahu beberapa unix, Anda bisa mencoba yang berikut:
Catatan: $ berarti prompt perintah
Katakanlah Anda memiliki file my_data.txt dengan konten seperti itu:
Kemudian menggunakan
os
modul Anda dapat menggunakansed
perintah yang biasaJika Anda tidak menyadari sed, periksa, ini sangat berguna.
sumber