2013-05-17 4 views
1

Я пытаюсь изменить некоторые строки в текстовом файле, не затрагивая другие строки. Это то, что находится внутри текстового файла под названием «text.txt»Чтение/запись текстового файла

this is a test1|number1 
this is a test2|number2 
this is a test3|number2 
this is a test4|number3 
this is a test5|number3 
this is a test6|number4 
this is a test7|number5 
this is a test8|number5 
this is a test9|number5 
this is a test10|number5 

Моя цель состоит в том, чтобы изменить линию 4 и 5 строки, но сохранить тот же отдых.

mylist1=[] 
for lines in open('test','r'): 
    a=lines.split('|') 
    b=a[1].strip() 
    if b== 'number3': 
     mylist1.append('{}|{} \n'.format('this is replacement','number7')) 
    else: 
     mylist1.append('{}|{} \n'.format(a[0],a[1].strip())) 
myfile=open('test','w') 
myfile.writelines(mylist1) 

Несмотря на то, что код работает, мне интересно, есть ли у него лучший и эффективный способ сделать это? Можно ли прочитать файл только по номеру строки?

+0

Вы не можете писать «линию» в произвольном месте, но если вы хотите знать, номер текущей строки при чтении, вы можете использовать 'enumerate', как в' for index, line in enumerate (open ('test', 'r')): '. Это может помочь, если вы действительно хотите идентифицировать строки по номерам, а не по местоположению.BTW: писать «для __lines__», как вы делаете, вводит в заблуждение - то, что вы получаете каждый раз через цикл, является линией __single__. – kampu

ответ

10

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

  • с использованием инструкции with;
  • избегая хранения строк в списке;
  • запись lines без форматирования в пункте else (если применимо).

Применяя все выше:

import shutil 
with open('test') as old, open('newtest', 'w') as new: 
    for line in old: 
     if line.rsplit('|', 1)[-1].strip() == 'number3': 
      new.write('this is replacement|number7\n') 
     else: 
      new.write(line) 
shutil.move('newtest', 'test') 
+0

Вы правы. Возможно, он может использовать файл в памяти (модуль StringIO) или временный файл (модуль tempfile), но в основном он ничего не может сделать в исходном файле. – Markon

+0

Почему это не работает, когда я меняю «newtest» на «test»? хотя я должен переписать, чтобы изменить файл, мне все равно нужно, чтобы оно имело то же имя. но спасибо за помощь –

+0

@ChrisAung Так как открытие файла в режиме записи обрезает его. Вы сразу теряете старый контент. Поэтому вы должны либо перенести файл, когда закончите (см. Мое редактирование), либо используйте 'fileinput', как предложил @jamylak; но если вы посмотрите на документы, 'fileinput' делает то же самое внутри: создает файл резервной копии, затем тихо удаляет его. –

2

Нет. Файлы байт-ориентированные, а не ориентированные на линию и изменяющие длину строки не будут продвигать следующие байты.

3
import fileinput 

for lines in fileinput.input('test', inplace=True): 
    # inplace=True redirects stdout to a temp file which will 
    # be renamed to the original when we reach the end of the file. this 
    # is more efficient because it doesn't save the whole file into memeory 
    a = lines.split('|') 
    b = a[1].strip() 
    if b == 'number3': 
     print '{}|{} '.format('this is replacement', 'number7') 
    else: 
     print '{}|{} '.format(a[0], a[1].strip()) 
0

попробовать это решение

with open('test', inplace=True) as text_file: 
    for line in text_file: 
     if line.rsplit('|', 1)[-1].strip() == 'number3': 
      print '{}|{} \n'.format('this is replacement', 'number7') 
     else: 
      print line 
0

Это не совсем ясно, ваше намерение состоит в том, следует ли идентифицировать линии заменить их стоимость, или их номер строки.

Если первое ваше намерение, вы можете получить список строк, как это:

with open('test','r') as f: 
    oldlines = f.read().splitlines() 

Если есть опасность замыкающие пробелы, вы можете также:

После этого вы можете обработать их как это:

newlines = [ line if not line.strip().endswith('|number3') else 'this is replacement|number7' for line in oldlines] 

Открыть файл назначения (я предполагаю, что вы хотите переписать оригинал, здесь), и записать все строки:

with open('test','w') as f: 
    f.write("\n".join(newlines)) 

Это общий шаблон, полезный для любой простой линейной фильтрации.

Если вы имели в виду, чтобы определить строки по номеру, вы можете просто изменить строку «Newlines»:

newlines = [ line if i not in (3, 4) else 'this is replacement|number7' for i, line in enumerate(oldlines)] 
Смежные вопросы