Saya menggunakan Python, dan ingin memasukkan string ke file teks tanpa menghapus atau menyalin file. Bagaimana saya bisa melakukan itu?
Saya menggunakan Python, dan ingin memasukkan string ke file teks tanpa menghapus atau menyalin file. Bagaimana saya bisa melakukan itu?
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.
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
with
pernyataan dalam Python 2.5 Anda perlu menambahkan "dari impor with_statement" di masa depan . Selain itu, membuka file dengan with
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 menggunakan inline=True
arg. Contoh di sini: stackoverflow.com/a/2363893/47390
f.Close()
The fileinput
modul 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 5th
for i, line in enumerate(fileinput.input('lorem_ipsum.txt', inplace=1)):
sys.stdout.write(line.replace('sit', 'SIT')) # replace 'sit' and write
if i == 4: sys.stdout.write('\n') # write a blank line after the 5th line
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.
import os
os.rename( aFile, aFile+"~" )
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.
import os
from mmap import mmap
def insert(filename, str, pos):
if len(str) < 1:
# nothing to insert
return
f = open(filename, 'r+')
m = mmap(f.fileno(), os.path.getsize(filename))
origSize = m.size()
# or this could be an error
if 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()
Menulis kelas kecil untuk melakukan ini dengan bersih.
import tempfile
class FileModifierError(Exception):
pass
class FileModifier(object):
def __init__(self, fname):
self.__write_dict = {}
self.__filename = fname
self.__tempfile = tempfile.TemporaryFile()
with open(fname, 'rb') as fp:
for line in fp:
self.__tempfile.write(line)
self.__tempfile.seek(0)
def write(self, s, line_number = 'END'):
if line_number != 'END' and not isinstance(line_number, (int, float)):
raise FileModifierError("Line number %s is not a valid number" % line_number)
try:
self.__write_dict[line_number].append(s)
except KeyError:
self.__write_dict[line_number] = [s]
def writeline(self, s, line_number = 'END'):
self.write('%s\n' % s, line_number)
def writelines(self, s, line_number = 'END'):
for ln in s:
self.writeline(s, line_number)
def __popline(self, index, fp):
try:
ilines = self.__write_dict.pop(index)
for line in ilines:
fp.write(line)
except KeyError:
pass
def close(self):
self.__exit__(None, None, None)
def __enter__(self):
return self
def __exit__(self, type, value, traceback):
with open(self.__filename,'w') as fp:
for index, line in enumerate(self.__tempfile.readlines()):
self.__popline(index, fp)
fp.write(line)
for index in sorted(self.__write_dict):
for line in self.__write_dict[index]:
fp.write(line)
self.__tempfile.close()
Maka Anda dapat menggunakannya dengan cara ini:
with FileModifier(filename) as fp:
fp.writeline("String 1", 0)
fp.writeline("String 2", 20)
fp.writeline("String 3") # To write at the end of the file
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:
$ cat my_data.txt
This is a data file
with all of my data in it.
Kemudian menggunakan os
modul Anda dapat menggunakan sed
perintah yang biasa
import os
# Identifiers used are:
my_data_file = "my_data.txt"
command = "sed -i 's/all/none/' my_data.txt"
# Execute the command
os.system(command)
Jika Anda tidak menyadari sed, periksa, ini sangat berguna.