Существует еще один очень удобный способ решения этой проблемы - использовать возможности параллелизма 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 .
Вы хотите сделать что-то вроде этого:
# 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».
Вы можете сделать это двумя способами, выберите то, что подходит вашему требованию:
Метод 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
Если ваш текст содержит только одного человека:
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
вы можете использовать fileinput для редактирования
import fileinput
for line in fileinput.FileInput("myfile", inplace=1):
if line .....:
print line
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')
Сегодня я практиковал работу над файлами и понял, что я могу основываться на ответе Йохена, чтобы обеспечить большую функциональность для повторного / многократного использования. К сожалению, мой ответ не затрагивает проблему работы с большими файлами, но облегчает жизнь в меньших файлах.
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))