@ А другой пост в любом случае является копией вставки строки в указанном месте текстового файла, и, конечно, здесь есть четкие составные ответы. Почему бы не добавить свой ответ здесь, а не наоборот? Принятый ответ не является обязательным требованием для хорошего вопроса.
Бхаргав Рао
@BhargavRao Голосование отменено. Я должен был найти этот дубликат, хотя!
Ани Менон
Ответы:
134
К сожалению, нет способа вставить в середину файла, не переписав его. Как указывалось в предыдущих постерах, вы можете добавить файл или перезаписать его, используя поиск, но если вы хотите добавить материал в начале или в середине, вам придется его переписать.
Это вещь операционной системы, а не Python. Это одинаково на всех языках.
Обычно я читаю из файла, вносю изменения и записываю его в новый файл myfile.txt.tmp или что-то в этом роде. Это лучше, чем чтение всего файла в память, потому что файл может быть слишком большим для этого. Как только временный файл будет завершен, я переименую его так же, как и исходный файл.
Это хороший, безопасный способ сделать это, потому что, если запись файла завершается сбоем или прерывается по какой-либо причине, у вас все еще остается нетронутый исходный файл.
Инструменты Unix, такие как awk / sed, делают что-то похожее в своем коде?
Маниш Гилл
Это не правда, что это одинаково на всех языках. В ActionScript: fileStream.openAsync (имя файла, FileMode.UPDATE); Затем я могу пойти куда угодно в файле и изменить что угодно.
ЭндрюБенджамин
2
@AndrewBenjamin Знаете ли вы, какие системные вызовы делает ActionScript? Есть ли вероятность, что openAsync читает файл и записывает новый после вызова?
AlexLordThorsen
@Rawrgulmuffins я не знаю. Однако я знаю, что он не читает весь файл в память, так как я использовал его для обработки файлов размером в несколько ГБ. Я подозреваю, что это то же самое, что писать с помощью C # streamwriter. Я рассматриваю python как инструмент для быстрого выполнения небольших задач, а не для крупномасштабной разработки и манипулирования файлами.
ЭндрюБенджамин
4
@AndrewBenjamin, пользователь не спрашивает о поиске в файле и его изменении (каждый язык, на котором я знаю, может это сделать); он спрашивает о вставке текста, который отличается от простого изменения / перезаписи того, что уже есть в файле. Возможно, в практическом применении это отличается, но ничего, что я могу найти в API-интерфейсе ActionScript, не указывает на то, что он ведет себя иначе, чем любой другой язык в этом отношении.
eestrada
104
Зависит от того, что вы хотите сделать. Чтобы добавить, вы можете открыть его с «а»:
with open("foo.txt","a")as f:
f.write("new line\n")
Если вы хотите подготовить что-то, сначала прочитайте файл:
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оператор в Python 2.5, вам нужно добавить «из будущего импорта с_statement». Помимо этого, открытие файлов с помощью withоператора определенно более читабельно и менее подвержено ошибкам, чем закрытие вручную.
Александр Кожевников
2
Вы можете рассмотреть fileinputвспомогательную библиотеку с ручками для грязной процедуры открытия / чтения / изменения / записи / замены при использовании inline=Trueаргумента arg. Пример здесь: stackoverflow.com/a/2363893/47390
mikegreenberg
3
Только не забудьте закрыть файл. f.Close()
Д.Розадо
5
Я не использую стиль, Д.Розадо, но при использовании со стилем я не думаю, что вам нужно закрывать вручную. С отслеживает ресурс, который он создает.
Крис
4
Вам не нужно вручную закрывать файл. В этом весь смысл использования «с» здесь. (Ну, на самом деле, Python делает это, как только объект файла собирается сборщиком мусора, что в CPython происходит, когда привязанное к нему имя выходит из области видимости ... но другие реализации этого не делают, и CPython может перестать делать это когда-нибудь поэтому рекомендуется "с")
Юрген А. Эрхард
71
fileinputМодуль стандартной библиотеки Python перепишет файл InPlace , если вы используете INPLACE параметр = 1:
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
Как это должно работать в python3? Я просто портировал приложение с таким кодом из python в python3, и я просто не мог заставить его работать правильно. Переменная 'line' является байтовым типом, я пытался декодировать ее в Unicode, а затем модифицировать и затем кодировать обратно в байты, но это просто не будет работать правильно. Это подняло какое-то исключение, которое я не могу вспомнить из головы. Люди с успехом используют fileinput inplace = 1 в python3?
Но это не проблема, потому что вы сначала проверили его на неважном файле, верно?
Паула Ливингстон
33
Перезапись файла на месте часто выполняется путем сохранения старой копии с измененным именем. Unix люди добавляют, ~чтобы отметить старый. Пользователи Windows делают разные вещи - добавляют .bak или .old - или полностью переименовывают файл, или помещают ~ в начале имени.
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()
Вместо этого shutilвы можете использовать следующее.
Выглядит хорошо. Хотите знать, если .readlines () лучше, чем итерация источника?
Боздоз
2
@bozdoz: итерация лучше, так как readlines читает весь файл. Не подходит для больших файлов. Конечно, это предполагает, что вы можете делать свои модификации таким локализованным способом. Иногда вы не можете, или ваш код становится намного сложнее.
Юрген А. Эрхард
@ S.Lott: os.rename(aFile, aFile + "~")изменит имя исходного файла, не создавая копию.
Patapoom
14
Модуль mmap Python позволит вам вставить в файл. В следующем примере показано, как это можно сделать в Unix (в Windows mmap может отличаться). Обратите внимание, что это не обрабатывает все ошибки, и вы можете повредить или потерять исходный файл. Кроме того, это не будет обрабатывать строки 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()
Это также возможно сделать без mmap с файлами, открытыми в режиме «r +», но это менее удобно и менее эффективно, так как вам придется читать и временно сохранять содержимое файла из позиции вставки в EOF - что может быть огромным
Как упоминал Адам, вы должны принять во внимание ограничения вашей системы, прежде чем вы сможете принять решение о подходе, достаточно ли у вас памяти, чтобы прочитать все это в память, заменить ее и переписать.
Если вы имеете дело с небольшим файлом или у вас нет проблем с памятью, это может помочь:
Вариант 1)
Считать весь файл в память, выполнить подстановку регулярных выражений для всей или части строки и заменить ее на эту строку плюс дополнительную строку. Вам нужно убедиться, что «средняя строка» уникальна в файле или если у вас есть временные метки в каждой строке, это должно быть довольно надежно.
# 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()
Вариант 2)
Определите среднюю линию и замените ее на эту строку плюс дополнительную строку.
# 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()
Ответы:
К сожалению, нет способа вставить в середину файла, не переписав его. Как указывалось в предыдущих постерах, вы можете добавить файл или перезаписать его, используя поиск, но если вы хотите добавить материал в начале или в середине, вам придется его переписать.
Это вещь операционной системы, а не Python. Это одинаково на всех языках.
Обычно я читаю из файла, вносю изменения и записываю его в новый файл myfile.txt.tmp или что-то в этом роде. Это лучше, чем чтение всего файла в память, потому что файл может быть слишком большим для этого. Как только временный файл будет завершен, я переименую его так же, как и исходный файл.
Это хороший, безопасный способ сделать это, потому что, если запись файла завершается сбоем или прерывается по какой-либо причине, у вас все еще остается нетронутый исходный файл.
источник
Зависит от того, что вы хотите сделать. Чтобы добавить, вы можете открыть его с «а»:
Если вы хотите подготовить что-то, сначала прочитайте файл:
источник
with
оператор в Python 2.5, вам нужно добавить «из будущего импорта с_statement». Помимо этого, открытие файлов с помощьюwith
оператора определенно более читабельно и менее подвержено ошибкам, чем закрытие вручную.fileinput
вспомогательную библиотеку с ручками для грязной процедуры открытия / чтения / изменения / записи / замены при использованииinline=True
аргумента arg. Пример здесь: stackoverflow.com/a/2363893/47390f.Close()
fileinput
Модуль стандартной библиотеки Python перепишет файл InPlace , если вы используете INPLACE параметр = 1:источник
Перезапись файла на месте часто выполняется путем сохранения старой копии с измененным именем. Unix люди добавляют,
~
чтобы отметить старый. Пользователи Windows делают разные вещи - добавляют .bak или .old - или полностью переименовывают файл, или помещают ~ в начале имени.Вместо этого
shutil
вы можете использовать следующее.источник
os.rename(aFile, aFile + "~")
изменит имя исходного файла, не создавая копию.Модуль mmap Python позволит вам вставить в файл. В следующем примере показано, как это можно сделать в Unix (в Windows mmap может отличаться). Обратите внимание, что это не обрабатывает все ошибки, и вы можете повредить или потерять исходный файл. Кроме того, это не будет обрабатывать строки Unicode.
Это также возможно сделать без mmap с файлами, открытыми в режиме «r +», но это менее удобно и менее эффективно, так как вам придется читать и временно сохранять содержимое файла из позиции вставки в EOF - что может быть огромным
источник
Как упоминал Адам, вы должны принять во внимание ограничения вашей системы, прежде чем вы сможете принять решение о подходе, достаточно ли у вас памяти, чтобы прочитать все это в память, заменить ее и переписать.
Если вы имеете дело с небольшим файлом или у вас нет проблем с памятью, это может помочь:
Вариант 1) Считать весь файл в память, выполнить подстановку регулярных выражений для всей или части строки и заменить ее на эту строку плюс дополнительную строку. Вам нужно убедиться, что «средняя строка» уникальна в файле или если у вас есть временные метки в каждой строке, это должно быть довольно надежно.
Вариант 2) Определите среднюю линию и замените ее на эту строку плюс дополнительную строку.
источник
Написал небольшой класс для этого чисто.
Тогда вы можете использовать это так:
источник
Если вы знаете какой-нибудь Unix, вы можете попробовать следующее:
Примечания: $ означает командную строку
Допустим, у вас есть файл my_data.txt с таким содержимым:
Затем с помощью
os
модуля вы можете использовать обычныеsed
командыЕсли вы не знаете о sed, проверьте это, это чрезвычайно полезно.
источник