Comparing line in external file with a variable and and replacing it - python

I'm trying to create a scoreboard in an external file in python and having a bit of an issue.
score = 14
with open("score.txt") as f:
data_1 = f.read()
lines = data_1.split("\n")
line_1 = lines[0]
line_1 = int(line_1)
if line_1 < score:
score = str(score)
with open("score.txt", "w") as a:
a.write(score)
Every time I'd run the code, it would write 14 in the first line and then delete everything else in the file.
I want the code to check if score is bigger than the first line in the file and if it is, shift everything down a line and put score there instead and if it is smaller than the first line do the same with the others

Related

How to replace strings in a text file using Python?

I am a newbie in programming and I'm trying to create a small text-based game with a high score feature. The game is fine, but I have a problem in trying to replace the highscore in the file if the player gets a higher score when the game is finished.
I created a function to make the file if it doesn't exist by using:
def createhighscore():
hs = os.listdir()
highscore = None
if "highscore.txt" not in hs:
highscore = open("highscore.txt", 'w')
a = ["normal null 0\n", "expert null 0\n"]
highscore.writelines(a)
return highscore
So now the highscore.txt file has two lines:
normal null 0
expert null 0
normal/expert = the gamemode the player picked, i put the gamemode in the variable "mode"
null = replaced with player name, i put the player name in the variable "player"
0 = replaced with the new highscore, i put the score in the variable "score"
I tried creating a code that split each word in each line into a list by using split(), and then checking if there is a condition where the score the player gets is higher than the current score for either mode. My code:
checkline = open("highscore.txt", "r+")
for line in checkline:
x = line.split()
if x[0] == mode.lower() and int(x[2]) < score:
line.replace(x[1], player)
line.replace(x[2], str(score))
print("NEW HIGHSCORE")
checkline.close()
checkline = open("highscore.txt", "r+")
for line in checkline:
x = line.split()
if x[0] == mode.lower() and int(x[2]) < score:
x[1] = player
x[2] = score
print("NEW HIGHSCORE")
checkline.close()
So if a player with the name "Raka" gets a score of 20 in Expert mode, the highscore.txt file should change to:
normal null 0
expert Raka 20
Sadly my code doesn't do anything and the content of the highscore.txt stays the same. I tried tweaking my code and until now I still haven't found the solution. I think my code does detect if the player gets a new highscore since "NEW HIGHSCORE" gets printed, but the text doesn't get replaced. I hope you guys can help me. Also, sorry for my bad English since it's not my first language. Thanks!
I made a simple script to write the changes in the highscores.txt, even if there are no changes the text file is overwritten.
score = 30
mode = "normal"
player = "Raka"
f = open("highscore.txt", "r")
lines = f.read().split("\n")
#remove empty lines in the lines list
lines = [line for line in lines if line.strip() != ""]
for x in range(0, len(lines)):
words = lines[x].split(" ")
if words[0] == mode and score > int(words[2]):
lines[x] = mode +" "+player+" "+str(score)
#Write the changes in highscore.txt
outF = open("highscore.txt", "w")
for line in lines:
outF.write(line)
outF.write("\n")
outF.close()
Try using the following code:
check_high_score = open("highscore.txt", "r")
list_high_scores = check_high_score.readlines()
check_high_score.close()
to_write = []
for score in list_high_scores:
if mode.lower() == "normal":
if int(list_high_scores[0][2]) < score:
to_write.append("normal " + player + " " + str(score))
else:
to_write.append(list_high_scores[0])
elif mode.lower() == "expert":
if int(list_high_scores[1][2]) < score:
to_write.append("expert " + player + " " + str(score))
else:
to_write.append(list_high_scores[1])
write_score = open("highscore.txt", "w")
write_score.writelines(to_write)
write_score.close()
I'd recommend storing the data in a new variable after opening a file rather than directly accessing it, makes it easier to logic on it and improves the code readability. Also, try to use different variable names each time you make a file-handler. As to why your code is not working, I think it's because you haven't closed the file with checkline.close() after replacing the contents. Unless you close the file, the program will not push the data from the cache to the disk and the contents will remain the same. Alternatively, you can also use the flush (checkline.flush() in your case) method to push the data into the file but keep in mind, in doing so, the file handler will keep running in the background and take memory while the close function will terminate it. Memory may not be a problem now but can be important in larger projects and it's good practice.

Saving Highscore in textfile for a game

I created a small game. I would like to save the 3 highest scores in a textfile and display them after the game. I created a textfile with following content: 0 0 0 (should represent the status before you play game for first time). I created 2 functions update_highscores() and display_highscores(), but nothing happens after finishing the game. the achieved scores are not stored in the text file and the highscores were not displayed after the game. How can i save and show the highscores?
def update_highscores():
global score, scores
file = "C:\Programmieren\Eigene Spiele\Catch The Bananas\highscores.txt"
scores=[]
with open(filename, "r") as file:
line = file.readline()
high_scores = line.split()
for high_score in high_scores:
if (score > int(high_score)):
scores.append(str(score) + " ")
score = int(high_score)
else:
scores.append(str(high_score) + " ")
with open (filename, "w") as file:
for high_score in scores:
file.write(high_score)
def display_highscores():
screen.draw.text("HIGHSCORES", (350,150), fontsize=40, color = "black")
y = 200
position = 1
for high_score in scores:
screen.draw.text(str(position) + ". " + high_score, (350, y), color = "black")
y = y + 25
position = position + 1
The update_highscores code should work fine if you change
file = "C:\Programmieren\Eigene Spiele\Catch The Bananas\highscores.txt"
to
filename = r"C:\Programmieren\Eigene Spiele\Catch The Bananas\highscores.txt"
The two things that changed were: changing file to filename, otherwise this code throws an exception because filename is not defined. I assume it's meant to be this way. The second thing I changed is adding an r before the string so that the backslashes are interpreted literally. Two other options that would also work are:
"C:\\Programmieren\\Eigene Spiele\\Catch The Bananas\\highscores.txt"
or
"C:/Programmieren/Eigene Spiele/Catch The Bananas/highscores.txt"
Just remember that a single backslash in a non-raw string will usually try to escape the next character.
Aside from that, just make sure that the file exists, and that it contains 0 0 0, or any sequence of characters separated by spaces. If the file is not initialized properly, there won't be any scores to replace.
This code works for me, so if there's still a problem, it's just with displaying the scores. They update in the file just fine. But I don't know what library you're using for screen, so I can't test that.
Oh, also: make sure you're actually calling the function. I assume it's elsewhere in your code and you just omitted it. Obviously, your code won't work if you don't call the function.
Here is my code that works. Just replace the path to highscores.txt and run this code by itself. If it works, the problem is somewhere else in your code, and we won't be able to help you unless you give us more of your code.
score = int(input("Enter new score: "))
scores = []
def update_highscores():
global score, scores
filename = r"path\to\highscores.txt"
scores=[]
with open(filename, "r") as file:
line = file.readline()
high_scores = line.split()
for high_score in high_scores:
if (score > int(high_score)):
scores.append(str(score) + " ")
score = int(high_score)
else:
scores.append(str(high_score) + " ")
with open (filename, "w") as file:
for high_score in scores:
print(high_score)
file.write(high_score)
update_highscores()
input()

Replace Line with New Line in Python

I am reading a text file and searching data line by line, based on some condition, changing some values in the line and writing it back into another file. The new file should not contain the old Line. I have tried the following, but it did not work. I think I am missing a very basic thing.
Solution: In C++ we can increment line but in Python I am not sure how to achieve this. So as of now, I am writing old line than new line. But in the new file, I want only the new line.
Example:
M0 38 A 19 40 DATA2 L=4e-08 W=3e-07 nf=1 m=1 $X=170 $Y=140 $D=8
M0 VBN A 19 40 TEMP2 L=4e-08 W=3e-07 nf=1 m=1 $X=170 $Y=140 $D=8
The code which i tried is the following:
def parsefile():
fp = open("File1", "rb+")
update_file = "File1" + "_update"
fp_latest = open(update_file, "wb+")
for line in fp:
if line.find("DATA1") == -1:
fp_latest.write(line)
if line.find("DATA1") != -1:
line = line.split()
pin_name = find_pin_order(line[1])
update_line = "DATA " + line[1] + " " + pin_name
fp_latest.write(update_line)
line = ''.join(line)
if line.find("DATA2") != -1:
line_data = line.split()
line_data[1] = "TEMP2"
line_data =' '.join(line_data)
fp_latest.write(line_data)
if line.find("DATA3") != -1:
line_data = line.split()
line_data[1] = "TEMP3"
line_data =' '.join(line_data)
fp_latest.write(line_data)
fp_latest.close()
fp.close()
The main problem with your current code is that your first if block, which checks for "DATA1" and writes the line out if it is not found runs when "DATA2" or "DATA3" is present. Since those have their own blocks, the line ends up being duplicated in two different forms.
Here's a minimal modification of your loop that should work:
for line in fp:
if line.find("DATA1") != -1:
data = line.split()
pin_name = find_pin_order(data[1])
line = "DATA " + data[1] + " " + pin_name
if line.find("DATA2") != -1:
data = line.split()
data[1] = "TEMP2"
line =' '.join(data)
if line.find("DATA3") != -1:
data = line.split()
data[1] = "TEMP3"
line =' '.join(data)
fp_latest.write(line)
This ensures that only one line is written because there's only a single write() call in the code. The special cases simply modify the line that is to be written. I'm not sure I understand the modifications you want to have done in those cases, so there may be more bugs there.
One thing that might help would be to make the second and third if statements into elif statements instead. This would ensure that only one of them would be run (though if you know your file will never have multiple DATA entries on a single line, this may not be necessary).
If you want to write a new line in a file replacing the old content that has been readed last time, you can use the file.seek() method for moving arround the file, there is an example.
with open("myFile.txt", "r+") as f:
offset = 0
lines = f.readlines()
for oldLine in lines:
... calculate the new line value ...
f.seek(offset)
f.write(newLine)
offset += len(newLine)
f.seek(offset)

Remove Space from Particular line In Textfile Python

I have textfiles that have the date stored on line 7 of each file, formatted as such:
Date: 1233PM 14 MAY 00
I would like to search through each file and get the new line 7 to be formatted as such:
Date: 1233PM 14 MAY 2000
So, basically, I just need to stick a '20' in front of the last two digits in line seven.
Probably not the most difficult problem, but I have been having difficulty as textfile.readlines() reads everything into the first (textfile[0]) position.
You can read all the file, change the specified line then save it again:
arc = open('file_name.txt').readlines()[0].split('\r')
#Do what you want with the 7th line i.e. arc[6]
new_arc = open('file_name.txt','w')
for line in arc:
new_arc.write(line)
new_arc.write('\n')
new_arc.close()
Maybe this:
with open(filename, 'r') as f:
lines = f.readlines()
with open(filename, 'w') as f:
for idx, line in lines:
if idx == 7: # or 6
vals = line.split()
if len(vals[-1]) == 2:
vals[-1] = '20'+vals[-1]
line = ' '.join(vals)
f.write(line)
Try this:
# open file
f = open("file.txt" , 'rU+b')
lines = f.readlines()
# modify line 7
lines[6] = lines[6][:-2] + "20" + lines[6][-2:]
# return file pointer to the top so we can rewrite the file
f.seek(0)
f.truncate()
# write the file with new content
f.write(''.join(lines))
f.close

How to search a word in a file and replace the entire line with a new line?

I have a file (with extension.hgx) that has some data like this:
length = 0.00000783
height = 48
RATIO = 2
X = 1.0
Y = 1.0
I would like to open the file and replace the two lines:
height = 48
RATIO = 2
With:
height = 8
RATIO = 8
I tried parsing the file and could search for the "height" and "RATIO". Unfortunately, I could not replace the line with new line and re-save the file. In my case the problem is that, that in the file the value of parameters e.g. height(=48) varies and sometimes has uneven spaces in between. I want to replace this complete line with--
height = 8
I have written the following code
import fileinput
import sys
f = open('test.hgx','r')
line_num = 0
search_phrase = "height"
for line in f.readlines():
line_num += 1
if line.find(search_phrase) >= 0:
print line_num
newline='height = 8'
lnum=1
for line in fileinput.FileInput("test.hgx",inplace=1):
if lnum==line_num:
result = newline+"\n"
else:
result=line
lnum=lnum+1
sys.stdout.write(result)
print line
This does not help replace complete line and save the file again. returns empty file.Any help would be greatly appreciated.
Regards,
Ris
How's this?
with open('test.hgx') as f: lines = f.read().splitlines()
with open('test.hgx', 'w') as f:
for line in lines:
if line.startswith('height') or line.startswith('RATIO'):
f.write(line.rsplit(' ', 1)[0] + ' 8\n')
else:
f.write(line + '\n')
you need to stop iterating in the first loop after finding the "height" line:
if line.find(search_phrase) >= 0:
print line_num
break
I propose to use regex tool:
import re
regx = re.compile('^(([^ \t]+)[ \t]+=.+)',re.MULTILINE)
new = '''\
RATIO = 8
sdjlkhbfvjhdbfjhsdoijhfsdhfksdhfh
height = 8
'''
dic = dict(mat.group(2,1) for mat in regx.finditer(new))
regchange = re.compile('^('+'|'.join(dic.iterkeys())+')[ \t]+=[^\r\n]+',re.MULTILINE)
with open(filename,'r+') as f:
content = f.read()
f.seek(0,0)
f.write(regchange.sub(lambda m: dic[m.group(1)],content))
f.truncate()
You put in new the lines you want to take place in the file, no matter in which order (that's why I wrote 'RATIO' line before 'height' line in my exemple, to show)
The program manages to obtain the dictionary dic that is used to create the regex that allows to search for the lines to be replaced and to substitute them with lines recorded in dic as values corresponding to the first name of the line
The line 'sdjlkhbfvjhdbfjhsdoijhfsdhfksdhfh' has no importance. I put it in new to show that the regex regx matches only with lines of the format 'name = something'
This code should work as-is. You have just to give a file's name to filename; If any error, give it please.

Categories