2012-05-22 3 views
3

Я хотел бы найти лучшее решение для достижения следующих трех этапов:Обновление строки в текстовом файле в определенном месте

  1. строк читать в данной строке
  2. строки обновления
  3. написать обновленные строки назад

Ниже приведен код, который работает, но мне интересно, есть ли какие-либо более простые (простые) решения?

new='99999' 

f=open('C:/Users/th/Dropbox/com/MS1Ctt-P-temp.INP','r+') 
lines=f.readlines() 
#the row number we want to update is given, so just load the content 
x = lines[95] 
print(x) 
f.close() 


#replace 
f1=open('C:/Users/th/Dropbox/com/MS1Ctt-P-temp.INP') 
con = f1.read() 
print con 
con1 = con.replace(x[2:8],new) #only certain columns in this row needs to be updated 
print con1 
f1.close() 


#write 
f2 = open('C:/Users/th/Dropbox/com/MS1Ctt-P-temp.INP', 'w') 
f2.write(con1) 
f2.close() 

Спасибо! UPDATE: получить представление от jtmoulia на этот раз становится легче

def replace_line(file_name, line_num, col_s, col_e, text): 
    lines = open(file_name, 'r').readlines() 
    temp=lines[line_num] 
    temp = temp.replace(temp[col_s:col_e],text) 
    lines[line_num]=temp 
    out = open(file_name, 'w') 
    out.writelines(lines) 
    out.close() 

ответ

1

Ну, чтобы начать с вами не должны держать повторное открытие и чтение из файла каждый раз. Режим r+ позволяет вам читать и записывать в данный файл.

Может быть что-то вроде

with open('C:/Users/th/Dropbox/com/MS1Ctt-P-temp.INP', 'r+') as f: 
    lines = f.readlines() 
    #... Perform whatever replacement you'd like on lines 
    f.seek(0) 
    f.writelines(lines) 

Кроме того, Editing specific line in text file in python

+0

@ C2H5OH спасибо за редактирование, этанол – jtmoulia

-1
FILENAME = 'C:/Users/th/Dropbox/com/MS1Ctt-P-temp.INP' 
lines = list(open(FILENAME)) 
lines[95][2:8] = '99999' 
open(FILENAME, 'w').write(''.join(lines)) 
+0

строки не изменяемы, т.е.'lines [95] [2: 8] = '99999' не будет работать. – mhawke

0

Когда я должен был сделать что-то подобное (для настройки Webmin), я сделал это полностью в PERL, потому что это то, что используется структура Webmin, и Мне было легко. Я предполагаю (но не знаю точно), есть эквивалентные вещи в Python. Сначала прочитайте весь файл в память сразу (способ PERL для этого, вероятно, называется «slurp»). (Эта идея хранения всего файла в памяти, а не только одна строка, используемая для того, чтобы не иметь смысла (или даже быть невозможным). Но в наши дни оперативная память настолько велика, что это единственный способ пойти.) Затем используйте оператор split для разделения файл в строки и поместить каждую строку в другой элемент гигантского массива. Затем вы можете использовать нужный номер строки в качестве индекса в массиве (помните, что индексы массива обычно начинаются с 0). Наконец, используйте «регулярное выражение» для изменения текста строки. Затем измените другую строку, другую и другую (или сделайте другое изменение в той же строке). Когда все будет готово, используйте join, чтобы поместить все строки в массив обратно в одну гигантскую строку. Затем напишите весь измененный файл.

Пока я не полный код удобно, вот примерный фрагмент часть кода PERL, так что вы можете увидеть, что я имею в виду:

our @filelines =(); 
our $lineno = 43; 
our $oldstring = 'foobar'; 
our $newstring = 'fee fie fo fum'; 
$filelines[$lineno-1] =~ s/$oldstring/$newstring/ig; 
# "ig" modifiers for case-insensitivity and possible multiple occurences in the line 
# use different modifiers at the end of the s/// construct as needed 
+0

Чтение всего файла в единственном пути, все еще не имеет смысла, размер файлов, с которыми мы можем иметь дело, увеличился, потому что f объем доступной памяти или наоборот. Для файлов, заявленных в диапазоне гигабайта, slurp станет дросселем. –

+0

Возможно, вы правы. По моему опыту любой текстовый файл - это то, что можно распечатать и взять в пиццерию, чтобы посмотреть. Такие файлы обычно варьируются от нескольких K до нескольких сотен K. У меня никогда не было никакого опыта с чем-либо удаленно, как текстовый файл гигабайта. (Тем не менее, я подозреваю, что в системе с 4 ГБ оперативной памяти использование массива сделает обработку текстового файла на 1 ГБ намного проще, чем может стоить. Старые привычки умирают. Мы читаем файлы по одной строке за раз уже более 40 лет, и хорошие причины для этого становятся довольно тонкими :-) –

+0

Спасибо за комментарий. Я думаю, что 'linecache.getline' может читать по строкам. Но я просто не уверен, как сохранить замененный на правильное положение. –

3

Проблема с текстовыми данными, даже когда табличными, заключается в том, что байтовые смещения не предсказуемы. Например, при представлении чисел со строками у вас есть один байт на цифру, тогда как при использовании двоичного кода (например, для двух) вам всегда нужны четыре или восемь байтов для малых и больших целых чисел.

Тем не менее, если ваш текстовый формат достаточно строгий, вы можете ладить, заменив байты, не изменяя размер файла, вы можете попробовать использовать standard mmap module. С его помощью вы сможете обрабатывать файл как байтовую строку mutable и изменять ее части на месте и позволять ядру сохранять файл для вас.

В противном случае любые другие ответы намного лучше подходят для решения проблемы.

+0

хорошая точка. Но некоторые из моих замен изменят длину строки, например, с изменением 0111 на 01110. Значит ли это, что mmap не работает для меня, не так ли? –

+0

Правильно, это не сработает. Изменение размера файла с помощью 'mmap' довольно сложнее, чем чтение/запись: вам нужно заранее знать размер нового файла, обрезать файл до этого размера, прежде чем сопоставлять файл, и переносить содержимое вручную, в зависимости от того, где вы выполнить изменения. – C2H5OH

Смежные вопросы