2016-11-27 8 views
3

Как заменить строку на другую внутри StringIO? - Я слышал, что это возможно, если они одинаковой длины.замена на месте в StringIO

Попытка:

from cStringIO import StringIO 

c = 'can\nhaz\nfoo' 

sio = StringIO(c) 

for line in sio: 
    if line == 'haz\n': 
     # sio.write('bar\n') 
     line = 'bar\n' 
     break 

sio.seek(0) 
sio.readlines() # [ 'can\n', 'haz\n', 'bar' ] 

PS: В настоящее время работает над решением в C, но предпочел бы сделать эту работу.

ответ

3

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

Небольшое другое изменение: cStringIO, созданный со строкой по умолчанию при запуске, не доступен для записи. Но вы можете обойти это путем создания пустого объекта и писать на нем (вы, очевидно, имеете доступ к write методу в настоящее время)

Что вы ищете:

c = 'can\nhaz\nfoo' 

sio = StringIO() 
sio.write(c) 
sio.seek(0) 

offset = sio.tell() 
for line in sio: 
    if line == 'haz\n': 
     sio.seek(offset) 
     sio.write('bar\n') 
     break 
    offset = sio.tell() 

Он хранит смещение перед тем Linearad и если шаблон найден, он возвращается к предыдущему смещению и записывает одинаковое количество байтов

Жестокое решение, если вы хотите использовать cStringIO: вы можете полностью прочитать буфер, выполнить замену и записать обратно к нему (позволяет заменить на более длинную кольца), но читает весь буфер, который, вероятно, не то, что вы хотите:

c = 'can\nhaz\nfoo' 

sio = StringIO(c) 

v = sio.getvalue() 
v = v.replace("haz","bar") 
sio.seek(0) 
sio.write(v) 

Обратите внимание, что Python 3 удалить эти объекты, теперь это просто io. Поэтому, полагаясь на такую ​​или такую ​​реализацию, ваш код не переносится.

+0

Спасибо, что сделал трюк, но небольшое изменение: 'AttributeError: 'объект cStringIO.StringIO' не имеет атрибута 'write''; переход к регулярному объекту 'StringIO.StringIO' решил эту проблему. Но теперь это не будет намного медленнее? :( –

+0

Извините, я просто заметил, что метод 'write' не существовал, если строка уже была заполнена. См. Мое редактирование, которое также работает с' cStringIO'. –

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

  • Нет связанных вопросов^_^