python encryption and decryption by using file - python

I am currently working on encrypting and decrypting files using python and I got to this part. I should replace original file with encryption dictionary and I tried to do so, but when I read the file and write it, it shows original text and encrypt version of it.
My original file contains the text, ABCDEF, and what I got for the result is ABCDEFGH!##$%^&*.
So I am not sure how to get rid of the original text.
Here is my code
import os
Dictionary = {'A':'!','B':'#','C':'#','D':'$','E':'%','F':'^'}
letterfile = input("What's the name of the file?")
exist = os.path.exists(letterfile)
if exist:
letterfile = open(letterfile, "r+")
readfile = letterfile.read()
for i in readfile:
if i in Dictionary:
letterfile.write(Dictionary[i])
letterfile.close()

You don't rewind to the beginning of the file when you write, so you're writing where the reading finished, which is the end of the file.
The right way to do this is to reopen the file for writing. That will empty the file and replace it with the encrypted version.
with open(letterfile, "r") as infile:
readfile = infile.read()
with open(letterfile, "w") as outfile:
for i in readfile:
letterfile.write(Dictionary.get(i, ""))

one way you can accomplish this by putting letterfile.truncate(0) after
readfile = letterfile.read() and before for i in readfile:
fully it would look like this
import os
Dictionary = {'A':'!','B':'#','C':'#','D':'$','E':'%','F':'^'}
letterfile = input("What's the name of the file?")
exist = os.path.exists(letterfile)
if exist:
letterfile = open(letterfile, "r+")
readfile = letterfile.read()
letterfile.truncate(0)
for i in readfile:
if i in Dictionary:
letterfile.write(Dictionary[i])
letterfile.close()

Related

How can I print the body of file that user provide the filename from input

I was wondering if there is anyway that from a filename provided by an user we can get the body of the file
Here as sample of my code
fname = input('Enter filename...')
fileObject = open(fname, 'r')
print(fname)
Yes, you need to read the data from the file and then print it out, or do everything at once:
fname = input("What's the file name? ")
# this assumes it's on the same directory
with open(fname, 'r') as file:
print(file.read())
You can try this: (read the official Python doc. too)
with open(filename) as f:
content = f.read()
# you may also want to remove whitespace characters like `\n` at the end of each line
print(content)

How to fix " AttributeError: 'int' object has no attribute 'replace' " while replacing and writing to a new file?

I have a hello.py file which asks user for their name and prints them a welcome message.
import subprocess
filename = "hello-name.txt"
fout = open("out.txt", "w")
with open(filename, "r+") as f:
lines = f.readlines()
your_name = input("What is your name? ")
title_name = your_name.title()
for line in lines:
line = fout.write(line.replace("[Name]", your_name))
line = fout.write(line.replace("[Title]", title_name))
print(line.strip())
subprocess.call(["notepad.exe", "out.txt"])
This is the content of my hello-name.txt file
Hello [Name]
Welcome to the world [Title]
My Question
When run hello.py it asks user for their Name and as soon as the name is entered, Python gives the following error :
line = fout.write(line.replace("[Title]", title_name))
AttributeError: 'int' object has no attribute 'replace'
Kindly help me to fix this issue.
Thank You
The write method returns the number of characters written, not the value written. Don't assign the result to line if you want to keep using it. If the goal is to perform both replacements before writing, do them both, then write, e.g.:
for line in lines:
line = line.replace("[Name]", your_name)
line = line.replace("[Title]", title_name)
fout.write(line)
There are two problems with this script:
As ShadowRanger pointed out, you're assigning the result from write to line; this overwrites the content.
You don't close the output file before opening it in Notepad.
An easy way to make sure a file is closed is to open it in a context, using the with keyword. You already did this when you read the input file; just do the same thing for the output file, and open Notepad after the with block (i.e. after you've written both lines and closed the file):
import subprocess
with open("hello-name.txt", "r+") as f:
lines = f.readlines()
your_name = input("What is your name? ")
title_name = your_name.title()
with open("out.txt", "w") as fout:
for line in lines:
line = line.replace("[Name]", your_name)
line = line.replace("[Title]", title_name)
fout.write(line)
print(line.strip())
subprocess.call(["notepad.exe", "out.txt"])
The return from fout.write is an integer. Then you are trying to replace on an integer (it isn't giving you the replaced line.
Try:
import subprocess
filename = "hello-name.txt"
fout = open("out.txt", "w")
with open(filename, "r+") as f:
lines = f.readlines()
your_name = input("What is your name? ")
title_name = your_name.title()
for line in lines:
line = line.replace("[Name]", your_name)
line = line.replace("[Title]", title_name)
fout.write(line)
print(line.strip())
fout.close()
subprocess.call(["notepad.exe", "out.txt"])
I changed it to a single fout since my guess is you don't want the double printing (but you can change it back). You probably also want to make the notepad call after parsing everything (and closing the file as others have mentioned)

how to rename a file and keep the original

I would like to keep unaltered the template.txt file after I insert some text into it and save the altered text file with a new name. Currently, my code overwrites the template.txt.
f = open("template.txt", "r")
contents = f.readlines()
f.close()
#insert the new text at line = 2
contents.insert(2, "This is a custom inserted line \n")
#open the file again and write the contents
f = open("template.txt", "w")
contents = "".join(contents)
f.write(contents)
f.close()
os.rename('template.txt', 'new_file.txt')
As people have mentioned, you're going to want to copy the contents of template.txt into a new file and then edit this new file. This allows you to keep the original file unmodified and you don't have to worry about renaming files at the end. Another tip: the with open(file) as f syntax keeps you from having to remember to close files when you're editing them and is the recommended way of working with files in python
with open("template.txt") as f:
lines = f.readlines()
with open("new_file.txt", "w+") as n:
lines.insert(2, "This is a custom inserted line \n")
n.writelines(lines)

Read a list from a file and append to it using Python

I have a file called usernames.py that may contain a list or does exist at all:
usernames.py
['user1', 'user2', 'user3']
In Python I now want to read this file if it exists and append to the list a new user or create a list with that user i.e. ['user3']
This is what I have tried:
with open(path + 'usernames.py', 'w+') as file:
file_string = host_file.read()
file_string.append(instance)
file.write(file_string)
This gives me an error unresolved 'append'. How can I achieve this? Python does not know it is a list and if the file does not exist even worst as I have nothing to convert to a list.
Try this:
import os
filename = 'data'
if os.path.isfile(filename):
with open(filename, 'r') as f:
l = eval(f.readline())
else:
l = []
l.append(instance)
with open(filename, 'w') as f:
f.write(str(l))
BUT this is quite unsafe if you don't know where the file is from as it could include any code to do anything!
It would be better not to use a python file for persistence -- what happens if someone slips you a usernames.py that has exploit code in it? Consider a csv file or a pickle, or just a text file with one user per line.
That said, if you don't open it as a python file, something like this should work:
from os.path import join
with open( join(path, 'usernames.py'), 'r+') as file:
file_string = file.read()
file_string = file_string.strip().strip('[').strip(']')
file_data = [ name.strip().strip('"').strip("'") for name in file_string.split(',' )]
file_data.append( instance )
file.fseek(0)
file.write(str(file_data))
If usernames contain commas or end in quotes, you have to be more careful.

Replace and overwrite instead of appending

I have the following code:
import re
#open the xml file for reading:
file = open('path/test.xml','r+')
#convert to string:
data = file.read()
file.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>",data))
file.close()
where I'd like to replace the old content that's in the file with the new content. However, when I execute my code, the file "test.xml" is appended, i.e. I have the old content follwed by the new "replaced" content. What can I do in order to delete the old stuff and only keep the new?
You need seek to the beginning of the file before writing and then use file.truncate() if you want to do inplace replace:
import re
myfile = "path/test.xml"
with open(myfile, "r+") as f:
data = f.read()
f.seek(0)
f.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>", r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", data))
f.truncate()
The other way is to read the file then open it again with open(myfile, 'w'):
with open(myfile, "r") as f:
data = f.read()
with open(myfile, "w") as f:
f.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>", r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", data))
Neither truncate nor open(..., 'w') will change the inode number of the file (I tested twice, once with Ubuntu 12.04 NFS and once with ext4).
By the way, this is not really related to Python. The interpreter calls the corresponding low level API. The method truncate() works the same in the C programming language: See http://man7.org/linux/man-pages/man2/truncate.2.html
file='path/test.xml'
with open(file, 'w') as filetowrite:
filetowrite.write('new content')
Open the file in 'w' mode, you will be able to replace its current text save the file with new contents.
Using truncate(), the solution could be
import re
#open the xml file for reading:
with open('path/test.xml','r+') as f:
#convert to string:
data = f.read()
f.seek(0)
f.write(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>",data))
f.truncate()
import os#must import this library
if os.path.exists('TwitterDB.csv'):
os.remove('TwitterDB.csv') #this deletes the file
else:
print("The file does not exist")#add this to prevent errors
I had a similar problem, and instead of overwriting my existing file using the different 'modes', I just deleted the file before using it again, so that it would be as if I was appending to a new file on each run of my code.
See from How to Replace String in File works in a simple way and is an answer that works with replace
fin = open("data.txt", "rt")
fout = open("out.txt", "wt")
for line in fin:
fout.write(line.replace('pyton', 'python'))
fin.close()
fout.close()
in my case the following code did the trick
with open("output.json", "w+") as outfile: #using w+ mode to create file if it not exists. and overwrite the existing content
json.dump(result_plot, outfile)
Using python3 pathlib library:
import re
from pathlib import Path
import shutil
shutil.copy2("/tmp/test.xml", "/tmp/test.xml.bak") # create backup
filepath = Path("/tmp/test.xml")
content = filepath.read_text()
filepath.write_text(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", content))
Similar method using different approach to backups:
from pathlib import Path
filepath = Path("/tmp/test.xml")
filepath.rename(filepath.with_suffix('.bak')) # different approach to backups
content = filepath.read_text()
filepath.write_text(re.sub(r"<string>ABC</string>(\s+)<string>(.*)</string>",r"<xyz>ABC</xyz>\1<xyz>\2</xyz>", content))

Categories

Resources