How can I delete and rewrite a line without unknown characters? - python

I have a database.txt file the first column is for usernames the second passwords and the rest 5 recovery question and answers alternating. I want to allow the user to be able to change the password of their details, without affecting another users username as they may be the same. I have found a way to delete the previous one and append the new line of modified details to the file. However, the is always a string or unknown characters at the start of the appended line. AND other characters are being changed not the second value in the list. Please help me find a way to avoid this.
https://repl.it/repls/NecessaryBoldButtonsYou can find the code here changing it will affect everyone, so please copy it elsewhere.
https://onlinegdb.com/BJbsn9-cL
I just need the password to be changed on a user input not other strings, the reason for all this code is that when changing a person's password another username could be changed.This is the original file
This is what happens afterwards, the second string in the list of the line which where data[0] = "bye" should only be changed to newpass, not all of the others
'''
import linecache
f = open("database.txt" , "r+")
for loop in range(3):
line = f.readline()
data = line.split(",")
if data[1] == "bye":
print(data[1]) #These are to help me understand what is happening
print(data[0])
b = data[0]
newpass = "Hi"
a = data[1]
fn = 'database.txt'
e = open(fn)
output = []
str="happy"
for line in e:
if not line.startswith(str):
output.append(line)
e.close()
print(output)
e = open(fn, 'w')
e.writelines(output)
e.close()
line1 = linecache.getline("database.txt" ,loop+1)
print(line)
password = True
print("Password Valid\n")
write = (line1.replace(a, newpass))
write = f.write(line1.replace(a, newpass))
f.close()
'''
This is the file in text:
username,password,Recovery1,Answer1,Recovery2,Answer2,Recovery3,Answer3,Recovery4,Answer4,
Recovery5,Answer5,o,o,o,o,o,o,o,o,o,o,
happy,bye,o,o,o,o,o,o,o,o,o,o,
bye,happy,o,o,o,o,o,o,o,o,o,o,
Support is very much appreciated
Feel free to change the code as much as you need to, as it is already a mess
Thanks in Advance

This should be pretty easy. The basic idea is:
open input file for reading
open output file for writing
for each line in input file
if password = "happy"
change user name in line
write line to output file
It should be pretty easy to convert that to python.
From comments, and by examining your code, I get the feeling that you're trying to update a line in-place. That is, it looks like your expectation is that given the file "database.txt" that contains this:
username,password,Recovery1,Answer1,Recovery2,Answer2,Recovery3,Answer3, Recovery4,Answer4,Recovery5,Answer5,
o,o,o,o,o,o,o,o,o,o,
happy,bye,o,o,o,o,o,o,o,o,o,o,
bye,happy,o,o,o,o,o,o,o,o,o,o,
When you make the change, your new "database.txt" will contain this:
username,password,Recovery1,Answer1,Recovery2,Answer2,Recovery3,Answer3, Recovery4,Answer4,Recovery5,Answer5,
o,o,o,o,o,o,o,o,o,o,
happy,Hi,o,o,o,o,o,o,o,o,o,o,
bye,happy,o,o,o,o,o,o,o,o,o,o,
You can do that, but you can't do it in-place. You have to write all the lines of the file, including the changed line, to a new temporary file. Then you can delete the old "database.txt" and rename the temporary file.
You can't update a line in a text file, because if you change the length of the line then you'll either end up with extra space at the end of the line you changed (because the new line has fewer characters than the old line), or you'll overwrite the beginning of the next line (the new line is longer than the old line).
The only other option is to load all of the lines into memory and close the file. Then change the line or lines you want to change, in memory. Finally, open the "database.txt" file for writing and output all of the lines from memory to the file.

Related

How to remove a blank line?

So basically, I'm making a password storage app, but when I write down the password the user enters in, python creates a blank line, which breaks my program. Heres a picture of it
So I'd need to get my program remove the second line somehow, but I couldn't figure out how to do it.
The part where I need help:
randompasswords = open("randomizedpsw.txt", "r")
choserandomnumber = random.randint(1, 39)
randomizedpassword = randompasswords.readlines()[choserandomnumber]
loginpsw = open('loginpsw.txt', 'w')
loginpsw.write(randomizedpassword)
loginpsw.close()
And so loginpsw.txt is the one with another empty line. That is what I need to remove somehow.
Here's a picture of the random password possibilities
.readlines() method returns a list containing each line in the file as a list item.
If you specify a size as argument to the method, it will read the file untill the byte size specified is reached.
Now the file you are reading in your third line of code with some random int value will return that much byte separated by \n.
So, the value of
randomizedpassword = randompasswords.readlines()[choserandomnumber]
would look something like ["content of line 1\n", "content of line 2\n"]
Hence the problem of \n arises when you are reading the file content ans storing it in a variable. The same gets written to the file later.
This is how you can get what you want , try this :
randompasswords = open("randomizedpsw.txt", "r")
choserandomnumber = random.randint(1, 39)
randomizedpassword = randompasswords.readlines()[choserandomnumber]
randomizedpassword = [line.rstrip('\n') for line in randomizedpassword] #if you have fetched multiple lines while reading lines, it will remove \n from all values.
loginpsw = open('loginpsw.txt', 'w')
loginpsw.write(randomizedpassword)
loginpsw.close()
You can see few examples of what values are returned by .readlines(size) method.
https://www.tutorialspoint.com/python/file_readlines.htm
This is because readlines() adds a line break. You have the option of using rstrip() an example would be:
with open('loginpsw.txt', 'w') as loginpsw: # automatically close file when done
loginpsw.write(randomizedpassword.rstrip('\n')) # strips last new line char
Important security note
The random library is not cryptographically secure use the secrets library instead.

Writing to the end of specific line in python

I have a text file that contains key value pairs separated by a tab like this:
KEY\tVALUE
I have opened this file in append mode(a+) so I can both read and write. Now it may happen that a particular key has more than 1 value. For that I want to be able to go to that particular key and write the next value beside original one separated by a some delimiter(or ,).
Here is what I wish to do:
import io
ft = io.open("test.txt",'a+')
ft.seek(0)
for line in ft:
if (line.split('\t')[0] == "querykey"):
ft.write(unicode("nextvalue"));#Write the another key value beside the original one
Now there are two problems with it:
I will iterate through the file to see on which line the key is present(Is there a faster way?)
I will write a string to the end of that line.
I would be grateful if I can get help with the second point.
The write function always writes at the end of file. How should I write to the end of a specific line? I have searched and have not got very clear answers as to how to do that
You can read whole of file content, do your edit and write edited content to file.
with open('test.txt') as f:
lines = f.readlines()
f= open('test.txt', 'w')#open file for write
for line in lines:
if line.split('\t')[0] == "querykey":
line = line + ',newkey'
f.write('\n'.join(lines))

adding a line to a txt file

I am trying to add a line to the end of a txt file. I have been reading some posts here and trying differents options, but, for some reason, the new line is neved added after the last one, it is just appended next to the last one.
So I was wondering what I am doing wrong....here I am showing my tests:
TEST 1:
#newProt is a new data entered by the user in this case 12345
exists = False
f = open('protocols.txt', 'a+')
for line in f:
if newProt == line:
exists = True
if not exists:
f.write(newProt)
f.close()
txt file after this code:
2sde45
21145
we34z12345
TEST 2:
exists = False
with open('protocols.txt', 'r+') as f:
for line in f:
if newProt == line:
exists = True
if not exists:
f.write(newProt)
txt file after this code: exactly the same as above...
And, like this, I have tested some combinations of letters to open the file, rb+, w, etc but for some reason I never get the desired output txt file:
2sde45
21145
we34z
12345
So I do not know what I am doing wrong, I am following some examples I gor from some other posts here.
Try this:
exists = False
f = open('protocols.txt', 'a+')
for line in f:
if newProt == line:
exists = True
if not exists:
f.write('\n' + newProt)
f.close()
This adds the new line character to the end of the file then adds 'newProt'.
EDIT:
The reason why your code did not produce the desired result is because you were simply writing a string to the file. New lines in text are not really 'in' the text file. The text file is literally a series of bytes known as chars. The reason why various applications such as text editors show you new lines is because it interprets certain characters as formatting elements rather than letters or numbers.
'\n' is one such formatting character (in the ASCII standard), and it tells your favorite text editor to start a new line. There are others such as '\t' which makes a tab.
Have a look at the wiki article on Newline character for more info
You can use f.seek(-x,x), reach the last line and then f.write().
Otherwise my understanding is if you open a file in "a" (append) mode, it'll anyways be written in the end
Refer to this link: Appending line to a existing file having extra new line in Python

Spell checking with custom dictionary

Need your guidance!
Want to check some text file for any spelling mistakes against custom dictionary.
Here is the code:
Dictionary=set(open("dictionary.txt").read().split())
print Dictionary
SearchFile = open(input("sample.txt"))
WordList = set()
for line in SearchFile:
line = line.strip()
if line not in Dictionary:
WordList.add(line)
print(WordList)
But when I open and check back the sample file nothing changed. What Im doing wrong?
What you are doing wrong is not explicitly changing anything in any file.
Here is a little bit of code to show how to write stuff to files...
fp = open(somefilepath,'w')
this line opens a file for writing, the 'w' tells python to create the file if it does not exist, but also deletes the contents of the file if it does exist. If you want to open a file for writing and keep the current contents use 'a' instead. 'a' is for append.
fp.write(stuff)
writes whatever is in the variable 'stuff' to the file.
Hope this helps. For code more specific to your problem please tell us what exactly you want to write to your file.
Also, here is some documentation that should help you to better understand the topic of files: http://docs.python.org/tutorial/inputoutput.html#reading-and-writing-files
EDIT: but you are not changing anything!
By the end of your script here is what you have accomplished:
1. Dictionary is a set containing all acceptable words
2. WordList is a set containing all not acceptable lines
3. You have read to the end of SearchFile
If I am understanding your question correctly what you want to now do is:
4. find out which Disctionary word each line stored in Wordlist should be
5. re-write SearchFile with the offending lines replaced.
If this is correct, how do you intend to figure out which WordList entry is supposed to be which Dictionary entry? How do you know the actual corrections? Have you attempted this part of the script (it is the crux, after all. It would only be polite). Can you please share with us your attempt at this part.
Lets assume you have this function:
def magic(line,dictionary):
"""
this takes a line to be checked, and a set of acceptable words.
outputs what line is meant to be.
PLEASE tell us your approach to this bit
"""
if line in dictionary:
return line
...do stuff to find out which word is being mis spelt, return that word
Dictionary=set(open("dictionary.txt").read().split())
SearchFile = open("sample.txt",'r')
result_text = ''
for line in SearchFile:
result_text += magic(line.strip(),Dictionary) #add the correct line to the result we want to save
result_text += '\n'
SearchFile = open("sample.txt",'w')
SearchFile.write(result_text) # here we actually make some changes
If you have not thought about how to find the actual dictionary value that mis-spelt lines should be corrected to become, try this out: http://norvig.com/spell-correct.html
To re-iterate a previous point, it is important that you show that you have at least attempted to solve the crux of your problem if you want any meaningful help.

Delete a row from a text file with Python

I have a file where each line starts with a number. The user can delete a row by typing in the number of the row the user would like to delete.
The issue I'm having is setting the mode for opening it. When I use a+, the original content is still there. However, tacked onto the end of the file are the lines that I want to keep. On the other hand, when I use w+, the entire file is deleted. I'm sure there is a better way than opening it with w+ mode, deleting everything, and then re-opening it and appending the lines.
def DeleteToDo(self):
print "Which Item Do You Want To Delete?"
DeleteItem = raw_input(">") #select a line number to delete
print "Are You Sure You Want To Delete Number" + DeleteItem + "(y/n)"
VerifyDelete = str.lower(raw_input(">"))
if VerifyDelete == "y":
FILE = open(ToDo.filename,"a+") #open the file (tried w+ as well, entire file is deleted)
FileLines = FILE.readlines() #read and display the lines
for line in FileLines:
FILE.truncate()
if line[0:1] != DeleteItem: #if the number (first character) of the current line doesn't equal the number to be deleted, re-write that line
FILE.write(line)
else:
print "Nothing Deleted"
This is what a typical file may look like
1. info here
2. more stuff here
3. even more stuff here
When you open a file for writing, you clobber the file (delete its current contents and start a new file). You can find this out by reading documentation for the open() command.
When you open a file for appending, you do not clobber the file. But how can you delete just one line? A file is a sequence of bytes stored on a storage device; there is no way for you to delete one line and have all the other lines automatically "slide down" into new positions on the storage device.
(If your data was stored in a database, you could actually delete just one "row" from the database; but a file is not a database.)
So, the traditional way to solve this: you read from the original file, and you copy it to a new output file. As you copy, you perform any desired edits; for example, you can delete a line simply by not copying that one line; or you can insert a line by writing it in the new file.
Then, once you have successfully written the new file, and successfully closed it, if there is no error, you go ahead and rename the new file back to the same name as the old file (which clobbers the old file).
In Python, your code should be something like this:
import os
# "num_to_delete" was specified by the user earlier.
# I'm assuming that the number to delete is set off from
# the rest of the line with a space.
s_to_delete = str(num_to_delete) + ' '
def want_input_line(line):
return not line.startswith(s_to_delete)
in_fname = "original_input_filename.txt"
out_fname = "temporary_filename.txt"
with open(in_fname) as in_f, open(out_fname, "w") as out_f:
for line in in_f:
if want_input_line(line):
out_f.write(line)
os.rename(out_fname, in_fname)
Note that if you happen to have a file called temporary_filename.txt it will be clobbered by this code. Really we don't care what the filename is, and we can ask Python to make up some unique filename for us, using the tempfile module.
Any recent version of Python will let you use multiple statements in a single with statement, but if you happen to be using Python 2.6 or something you can nest two with statements to get the same effect:
with open(in_fname) as in_f:
with open(out_fname, "w") as out_f:
for line in in_f:
... # do the rest of the code
Also, note that I did not use the .readlines() method to get the input lines, because .readlines() reads the entire contents of the file into memory, all at once, and if the file is very large this will be slow or might not even work. You can simply write a for loop using the "file object" you get back from open(); this will give you one line at a time, and your program will work with even really large files.
EDIT: Note that my answer is assuming that you just want to do one editing step. As #jdi noted in comments for another answer, if you want to allow for "interactive" editing where the user can delete multiple lines, or insert lines, or whatever, then the easiest way is in fact to read all the lines into memory using .readlines(), insert/delete/update/whatever on the resulting list, and then only write out the list to a file a single time when editing is all done.
def DeleteToDo():
print ("Which Item Do You Want To Delete?")
DeleteItem = raw_input(">") #select a line number to delete
print ("Are You Sure You Want To Delete Number" + DeleteItem + "(y/n)")
DeleteItem=int(DeleteItem)
VerifyDelete = str.lower(raw_input(">"))
if VerifyDelete == "y":
FILE = open('data.txt',"r") #open the file (tried w+ as well, entire file is deleted)
lines=[x.strip() for x in FILE if int(x[:x.index('.')])!=DeleteItem] #read all the lines first except the line which matches the line number to be deleted
FILE.close()
FILE = open('data.txt',"w")#open the file again
for x in lines:FILE.write(x+'\n') #write the data to the file
else:
print ("Nothing Deleted")
DeleteToDo()
Instead of writing out all lines one by one to the file, delete the line from memory (to which you read the file using readlines()) and then write the memory back to disk in one shot. That way you will get the result you want, and you won't have to clog the I/O.
You could mmap the file... after haven read the suitable documentation...
You don't need to check for the lines numbers in your file, you can do something like this:
def DeleteToDo(self):
print "Which Item Do You Want To Delete?"
DeleteItem = int(raw_input(">")) - 1
print "Are You Sure You Want To Delete Number" + str(DeleteItem) + "(y/n)"
VerifyDelete = str.lower(raw_input(">"))
if VerifyDelete == "y":
with open(ToDo.filename,"r") as f:
lines = ''.join([a for i,a in enumerate(f) if i != DeleteItem])
with open(ToDo.filename, "w") as f:
f.write(lines)
else:
print "Nothing Deleted"

Categories