0

I am trying to make a game, where your score saves as a text file. The score (clicks) must always be on the second line and save per user. Every time a user saves, I would like the second line of the text file to be replaced with the new score.

I have tried using loads of things suggested on stack overflow, like the os.replace or os.resub, but none work.

def save():
    global userlog
    global clicks
    score = open(directory + "/" + userlog + ".txt", "r+")
#### On this line, I want some code that will replace the second line in the text file listed above.
    for i in range(random.randint(2,5)):
        print("Saving")
        time.sleep(0.10)
        print("Saving.")
        time.sleep(0.10)
        print("Saving..")
        time.sleep(0.10)
        print("Saving...")
        time.sleep(0.10)
    print("\nGame Saved Sucessfully!")

I have not had anything work. Just getting some standard error messages.

Any help will be appreciated :)

Thanks :)

Bryan Oakley
  • 370,779
  • 53
  • 539
  • 685
JJ Kenna
  • 1
  • 1
  • no, as far as I know. just had a similar question [here](https://stackoverflow.com/questions/58078287/search-a-string-in-a-text-file-and-copy-and-paste-that-line-in-same-text-file). what you can do is load the text to a variable, edit the variable on save, write the variable back to the text file. not even needs `os`. – FObersteiner Sep 24 '19 at 13:30
  • But I want to later on in the program read the 2nd line, and can't just keep adding scored on save. I need some code that will set the second line to (clicks) upon clicking save. – JJ Kenna Sep 24 '19 at 13:32
  • to clarify: I meant edit the variable if the 'save' operation is called. so your `save()` function must include: load logfile, edit loaded data, write data back to logfile (overwrite existing or create new). – FObersteiner Sep 24 '19 at 13:37
  • by the way, `os.replace` renames a file, see [here](https://docs.python.org/3/library/os.html) (scroll down a bit). a bit missleading I would say ;-) – FObersteiner Sep 24 '19 at 13:54
  • Oh wow, that could actually be pretty useful :) – JJ Kenna Sep 24 '19 at 13:55
  • Could I use the script that you gave me to change passwords, usernames and more? That would be perfect! – JJ Kenna Sep 24 '19 at 13:55
  • In principle, yes. Although I would suggest not to save passwords in plain text. You could use e.g. `string.replace` (see [here](https://stackoverflow.com/questions/9452108/how-to-use-string-replace-in-python-3-x)) and so on... – FObersteiner Sep 24 '19 at 14:03

1 Answers1

1

an illustration of my comment - your save function could do something like

# load previously logged information
with open(logfile, 'r') as fobj:
    log = fobj.readlines()

# replace line 2 with some new info
log[1] = 'some new info\n'

# overwrite existing logfile        
with open(logfile, 'w') as fobj:
    for line in log:
        fobj.write(line)

In principle you could also use open() in r+ mode as you wrote in the question. That would require you to use seek() (see e.g. here) to get the file pointer to the position you want to write at - a more complicated option which I would not recommend.

FObersteiner
  • 22,500
  • 8
  • 42
  • 72
  • This is exactly what I needed! Thank you so much. Just to clarify, what does "fobj" mean? I am still a baby at python :p You are not the hero we deserved. You are the hero we needed chief ;-; – JJ Kenna Sep 24 '19 at 13:48
  • @JJKenna: I use `fobj` as a short form for "file object" - that is what `open()` returns (see e.g. [here](https://docs.python.org/3/library/functions.html#open)). More on the `with` statement e.g. [here](https://www.geeksforgeeks.org/with-statement-in-python/) - just a convenient way of having the garbage collection (`.close()` etc.) being done for you. – FObersteiner Sep 24 '19 at 13:52
  • Thank you for explaining. This makes a lot of sense to me now. :) – JJ Kenna Sep 24 '19 at 13:54
  • I am getting this error, I do no think it is too major, and could be fixable. Could you please check to see what is wrong? ```python line 19, in save log[1] = clicks IndexError: list assignment index out of range ``` my current code is ```python def save(): global userlog global clicks with open(directory + "/" + userlog + ".txt", "r") as fobj: log = fobj.readlines() log[1] = clicks with open(directory + "/" + userlog + ".txt", "w") as fobj: for line in log: fobj.write(line) ``` – JJ Kenna Sep 24 '19 at 14:01
  • @JJKenna your logfile does not seem to contain more than one line if you can't access `log` at index 1. print `log` for debugging, and if you write to the file, don't forget to add the new line `'\n'` - otherwise, `.readlines()` will not know where a line ends when the file is re-loaded. – FObersteiner Sep 24 '19 at 14:06
  • In my script, you create 2 lines. Your username, and your score. I would like to edit line 2. – JJ Kenna Sep 24 '19 at 14:10
  • then the content of your logfile should look like 'username\n' in the first line and 'score\n' in the second line. – FObersteiner Sep 24 '19 at 14:14
  • ```python log[1] = clicks IndexError: list assignment index out of range ``` I changed where it writes the score in the first place and added a \n, still getting this error. ```python data.write("0\n") ``` – JJ Kenna Sep 24 '19 at 14:18
  • https://pastebin.com/CZmrC0Dv here is my entire script if it can help you help me solve the issue :) – JJ Kenna Sep 24 '19 at 14:47
  • @JJKenna: sorry, had to go offline yesterday. I think the error you got was due to a missing newline as I noted above. the line `log[1] = clicks` should be something like `log[1] = str(clicks) + '\n'` or `log[1] = f"{clicks}\n"` in f-string notation. Besides the newline, note that clicks is an integer - to write it to a text file, you'll have to format it as string. – FObersteiner Sep 25 '19 at 06:53
  • oh my god it works. you are amazing! thank you so much. JJ. – JJ Kenna Sep 25 '19 at 12:25
  • @JJKenna: great, glad I could help! – FObersteiner Sep 25 '19 at 12:32
  • how can i make my program read from the second line as an integer? i have printed the "clicks" when the program starts and all i get is "[]". – JJ Kenna Sep 25 '19 at 12:50
  • @JJKenna: if the line read from the file prints as "[]", it seems to me that the line did not contain anything. if read correctly, it should print as "5\n" (if the score was 5). you can then convert `line` to integer by `int(line)`. Also, in your linked code, I noted that `register_screen()` has a line `data = open(...`. If you don't use `with...`, make sure to add `data.close()` when you're done writing. – FObersteiner Sep 25 '19 at 14:19
  • eek. i did something and it completely broke my code. cannot fix it :/ https://pastebin.com/vTi18XvV – JJ Kenna Sep 26 '19 at 11:09
  • @JJKenna: you're still on this? Your code sort-of runs with slight modifications like: remove `clicks = userlog.readlines(2)` You'll have to properly read the logfile here, you know how to do this by now ;-). second, don't use `import *` - explicitly say what you import like `from tkinter import Tk, Button, Label` - much more readable! – FObersteiner Sep 26 '19 at 17:19