Python & mdash; Редактирование конкретной строки в txt-файле без записи всего файла [duplicate]

Существует еще один очень удобный способ решения этой проблемы - использовать возможности параллелизма rxJava. Вы можете выполнить любую задачу в фоновом режиме и опубликовать результаты в основном потоке очень удобным способом, поэтому эти результаты будут переданы цепочке обработки.

Первый проверенный ответ - использование AsynTask. Да, это решение, но сейчас оно устарело, потому что вокруг есть новые инструменты.

String getUrl() {
    return "SomeUrl";
}

private Object makeCallParseResponse(String url) {
    return null;
    //
}

private void processResponse(Object o) {

}

Метод getUrl предоставляет URL-адрес, и он будет выполнен в основном потоке.

makeCallParseResponse (..) - делает фактическую работу

processResponse (..) - обрабатывает результат по основному потоку.

Код для асинхронного выполнения будет выглядеть так:

rx.Observable.defer(new Func0<rx.Observable<String>>() {
    @Override
    public rx.Observable<String> call() {
        return rx.Observable.just(getUrl());
    }
})
    .subscribeOn(Schedulers.io())
    .observeOn(Schedulers.io())
    .map(new Func1<String, Object>() {
        @Override
        public Object call(final String s) {
            return makeCallParseResponse(s);
        }
    })
    .observeOn(AndroidSchedulers.mainThread())
    .subscribe(new Action1<Object>() {
        @Override
        public void call(Object o) {
             processResponse(o);
        }
    },
    new Action1<Throwable>() {
        @Override
        public void call(Throwable throwable) {
            // Process error here, it will be posted on
            // the main thread
        }
    });

По сравнению с AsyncTask этот метод позволяет переключать планировщики произвольным числом раз (скажем, извлекать данные на одном планировщике и обрабатывать эти данные на другом (скажем, Scheduler.computation ()). также можно определить собственные планировщики.

Чтобы использовать эту библиотеку, включите следующие строки в файл build.gradle:

   compile 'io.reactivex:rxjava:1.1.5'
   compile 'io.reactivex:rxandroid:1.2.0'

Последняя зависимость включает в себя поддержку .mainThread ().

Существует отличная книга g0 для rx-java .

49
задан Martin Thoma 19 March 2014 в 01:01
поделиться

6 ответов

Вы хотите сделать что-то вроде этого:

# with is like your try .. finally block in this case
with open('stats.txt', 'r') as file:
    # read a list of lines into data
    data = file.readlines()

print data
print "Your name: " + data[0]

# now change the 2nd line, note that you have to add a newline
data[1] = 'Mage\n'

# and write everything back
with open('stats.txt', 'w') as file:
    file.writelines( data )

Причина в том, что вы не можете сделать что-то вроде «change line 2» непосредственно в файле. Вы можете только перезаписывать (не удалять) части файла - это означает, что новый контент просто покрывает старый контент. Итак, если вы написали «Маг» по строке 2, результирующая строка будет «Mageior».

68
ответ дан Jochen Ritzel 25 August 2018 в 04:49
поделиться

Вы можете сделать это двумя способами, выберите то, что подходит вашему требованию:

Метод I.) Замена с использованием номера строки. Вы можете использовать встроенную функцию enumerate() в этом случае:

Сначала в режиме чтения все данные в переменной

with open("your_file.txt",'r') as f:
    get_all=f.readlines()

Во-вторых, напишите в файл (где enumerate)

with open("your_file.txt",'w') as f:
    for i,line in enumerate(get_all,1):         ## STARTS THE NUMBERING FROM 1 (by default it begins with 0)    
        if i == 2:                              ## OVERWRITES line:2
            f.writelines("Mage\n")
        else:
            f.writelines(line)

Метод II.) Используя ключевое слово, которое вы хотите заменить:

Откройте файл в режиме чтения и скопируйте содержимое к списку

with open("some_file.txt","r") as f:
    newline=[]
    for word in f.readlines():        
        newline.append(word.replace("Warrior","Mage"))  ## Replace the keyword while you copy.  

«Воин» заменен на «Маг», поэтому напишите обновленные данные в файл:

with open("some_file.txt","w") as f:
    for line in newline:
        f.writelines(line)

Это то, что будет на выходе в обоих случаях:

Dan                   Dan           
Warrior   ------>     Mage       
500                   500           
1                     1   
0                     0           
1
ответ дан Aseem Yadav 25 August 2018 в 04:49
поделиться

Если ваш текст содержит только одного человека:

import re

# creation
with open('pers.txt','wb') as g:
    g.write('Dan \n Warrior \n 500 \r\n 1 \r 0 ')

with open('pers.txt','rb') as h:
    print 'exact content of pers.txt before treatment:\n',repr(h.read())
with open('pers.txt','rU') as h:
    print '\nrU-display of pers.txt before treatment:\n',h.read()


# treatment
def roplo(file_name,what):
    patR = re.compile('^([^\r\n]+[\r\n]+)[^\r\n]+')
    with open(file_name,'rb+') as f:
        ch = f.read()
        f.seek(0)
        f.write(patR.sub('\\1'+what,ch))
roplo('pers.txt','Mage')


# after treatment
with open('pers.txt','rb') as h:
    print '\nexact content of pers.txt after treatment:\n',repr(h.read())
with open('pers.txt','rU') as h:
    print '\nrU-display of pers.txt after treatment:\n',h.read()

Если ваш текст содержит несколько человек:

import re

# creation
with open('pers.txt','wb') as g:
    g.write('Dan \n Warrior \n 500 \r\n 1 \r 0 \n Jim  \n  dragonfly\r300\r2\n10\r\nSomo\ncosmonaut\n490\r\n3\r65')

with open('pers.txt','rb') as h:
    print 'exact content of pers.txt before treatment:\n',repr(h.read())
with open('pers.txt','rU') as h:
    print '\nrU-display of pers.txt before treatment:\n',h.read()


# treatment
def ripli(file_name,who,what):
    with open(file_name,'rb+') as f:
        ch = f.read()
        x,y = re.search('^\s*'+who+'\s*[\r\n]+([^\r\n]+)',ch,re.MULTILINE).span(1)
        f.seek(x)
        f.write(what+ch[y:])
ripli('pers.txt','Jim','Wizard')


# after treatment
with open('pers.txt','rb') as h:
    print 'exact content of pers.txt after treatment:\n',repr(h.read())
with open('pers.txt','rU') as h:
    print '\nrU-display of pers.txt after treatment:\n',h.read()

Если " работа "человека была постоянной длины в текте, вы могли бы изменить только часть текста, соответствующую« заданию »желаемого человека: это та же идея, что и у senderle.

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

from cPickle import dump, load

with open('cards','wb') as f:
    dump({'Dan':['Warrior',500,1,0],'Jim':['dragonfly',300,2,10],'Somo':['cosmonaut',490,3,65]},f)

with open('cards','rb') as g:
    id_cards = load(g)
print 'id_cards before change==',id_cards

id_cards['Jim'][0] = 'Wizard'

with open('cards','w') as h:
    dump(id_cards,h)

with open('cards') as e:
    id_cards = load(e)
print '\nid_cards after change==',id_cards
2
ответ дан eyquem 25 August 2018 в 04:49
поделиться

вы можете использовать fileinput для редактирования

import fileinput
for  line in fileinput.FileInput("myfile", inplace=1):
    if line .....:
         print line
14
ответ дан ghostdog74 25 August 2018 в 04:49
поделиться
def replace_line(file_name, line_num, text):
    lines = open(file_name, 'r').readlines()
    lines[line_num] = text
    out = open(file_name, 'w')
    out.writelines(lines)
    out.close()

И затем:

replace_line('stats.txt', 0, 'Mage')
11
ответ дан Peter C 25 August 2018 в 04:49
поделиться

Сегодня я практиковал работу над файлами и понял, что я могу основываться на ответе Йохена, чтобы обеспечить большую функциональность для повторного / многократного использования. К сожалению, мой ответ не затрагивает проблему работы с большими файлами, но облегчает жизнь в меньших файлах.

with open('filetochange.txt', 'r+') as foo:
    data = foo.readlines()                  #reads file as list
    pos = int(input("Which position in list to edit? "))-1  #list position to edit
    data.insert(pos, "more foo"+"\n")           #inserts before item to edit
    x = data[pos+1]
    data.remove(x)                      #removes item to edit
    foo.seek(0)                     #seeks beginning of file
    for i in data:
        i.strip()                   #strips "\n" from list items
        foo.write(str(i))
0
ответ дан theYnot 25 August 2018 в 04:49
поделиться
Другие вопросы по тегам:

Похожие вопросы: