i have this script : http://pastebin.com/JypqErN5
in this moment the function working input output file :
encrypt_file(in_file, out_file, password):
need input output to same file, simile to this :
encrypt_file(in_file, password):
im try to make same name input output bat not encrypt file correctly.
the function is this :
def encrypt_file(input_file, output_file, password):
with open(input_file, 'rb') as in_file, open(output_file, 'wb') as out_file:
encrypt(in_file, out_file, password)
how can i make this edits ? thanks all
You can't generally read from and write to a file at the same time.
So, you have two basic options.
First, you can read into memory, then encrypt, then write back out. Hopefully you have an encrypt function that works on strings rather than files. Since you've tagged this pycrypto, and all of its engines work on strings, this should be trivial. But if you have to use files, you can usually use BytesIO (or, for 2.x, cStringIO.StringIO), which wraps up a byte string in a file-like object, like this:
def encrypt_file(path, password):
temp = io.BytesIO()
with open(path, 'rb') as in_file:
encrypt(in_file, temp, password)
with open(path, 'wb') as out_file:
out_file.write(temp.getvalue())
This is dead simple, but of course it could be a problem if your files are gigantic.
Or you can write to a NamedTemporaryFile, then replace the original file with the temporary:
def encrypt_file(path, password):
dir = os.path.dirname(path)
with open(path, 'rb') as in_file, tempfile.NamedTemporaryFile(dir=dir, delete=False) as out_file:
encrypt(in_file, temp, password)
os.replace(temp.name, path)
This has some major advantages over the other method—it doesn't necessarily take a ton of memory (that depends on how encrypt is written), and there's no chance of leaving behind a partially-written file if you pull the plug (os.replace is atomic—it either happens completely, or not at all). But it's a little more complicated. And, before Python 3.3, there was no replace function. On Unix, rename works just as well. On Windows… well, that's a whole mess.
Related
I'm not running into any error just the output for my program is doing something strange. I've also noticed this thread here: Encrypt file with AES-256 and Decrypt file to its original format. This is my own approach to this issue, so I hope this isn't considered a duplicate. I'll post my code below, and explain how it functions. (Not including the encryption code)
For Encryption
path = 'files/*'
files = glob.glob(path)
with open('extensions.txt', 'w') as extension:
for listing in files:
endfile = os.path.splitext(listing)[1]
extension.write(endfile + "\n")
extension.close()
for in_filename in files:
out_filename1 = os.path.splitext(in_filename)[0]
out_filename = out_filename1 + '.pycrypt'
with open(in_filename, 'rb') as in_file, open(out_filename, 'wb') as out_file:
encrypt(in_file, out_file, password)
in_file.close()
out_file.close()
os.remove(in_filename)
print 'Files Encrypted'
For Decryption
password = raw_input('Password-> ')
path = 'files/*'
files = glob.glob(path)
for in_filename in files:
f=open('extensions.txt')
lines=f.readlines()
counter+=1
out_filename1 = os.path.splitext(in_filename)[0]
out_filename = out_filename1 + lines[counter]
with open(in_filename, 'rb') as in_file, open(out_filename, 'wb') as out_file:
decrypt(in_file, out_file, password)
in_file.close()
out_file.close()
os.remove(in_filename)
print 'Files Decrypted'
The code takes all the files in a folder, and encrypts them using AES. Then changes all the files extensions to .pycrypt, saving the old extension(s) into a file called "extensions.txt". After decryption it gives the files there extensions back by reading the text file line by line.
Here's the issue, after decryption every file goes from this:
15.png, sam.csv
To this
15.png, sam.csv
I've also noticed that if I re-encrypted the files with the symbol, the "extensions.txt" go from this:
15.png
sam.csv
bill.jpeg
To this (notice the spaces):
15.png
sam.csv
bill.jpeg
Any ideas what is causing this?
Let's read the documentation (emphasis mine):
file.readline([size])
Read one entire line from the file. A trailing newline character is kept in the string (but may be absent when a file ends with an
incomplete line). [6] If the size argument is present and
non-negative, it is a maximum byte count (including the trailing
newline) and an incomplete line may be returned. When size is not 0,
an empty string is returned only when EOF is encountered immediately.
file.readlines([sizehint])
Read until EOF using readline() and return a list containing the lines thus read. If the optional sizehint argument is present, instead
of reading up to EOF, whole lines totalling approximately sizehint
bytes (possibly after rounding up to an internal buffer size) are
read. Objects implementing a file-like interface may choose to ignore
sizehint if it cannot be implemented, or cannot be implemented efficiently.
This means that lines[counter] doesn't only contain the file extension, but also the newline character after that. You can remove all whitespace at the beginning and end with: lines[counter].strip().
A better way to do this is to encrypt a file "a.jpg" as "a.jpg.enc", so you don't need to store the extension in a separate file.
I need to write a program that reads a cipher text. I'm confused on how to import the needed text. Is this right? What if I have more than one cipher text to import?
def MultiAlphaCipher():
import MyCipherText.txt
Try something like:
with open("MyCipherText.txt") as f:
cipher_text = f.read()
If you are just reading the contents of a plain encrypted text file:
def read_file():
f=file('MyFile.txt', 'r') ## For files like ".txt"
content = f.read()
f.close()
return content
file_stuff = read_file() ## Will return the contents of "MyFile.txt" or whatever the filename is!
There are other conventions on reading a file like using "open" or "with", but that'll do untill you get better...
Also, in my experience of cryptography, I suggest using a diffrrent read mode or possibly encoding.
f = file("MyFile.doc", "rb") ## For files like ".pdf", ".rtf" or any file that uses font, color, etc
That will open the file in "read binary" mode which is helpful if you're encrypting/deceypting files outside plain ASCII. Then when writting to a file, you'll use mode "w" or "wb" to "write binary"
Hope that helps!
Additonal Tips:
If that is your actual code:
Import is used to import modules/libraries (other programs)
Import any module at the beginning and outside of functions/iterations
I'm looking for a small easy program to scramble and descramble a file's contents. The file is a zip file so it might contain any characters. Was thinking something like two's complement or something, but not sure how to do it in Python.
The reason for this is that my current employer has draconian internet and file installation laws and I would like to mail myself files without the mailer detecting the attachment as a zip file (which it does even if you rename it to .jpg).
I already have Python installed on my work machine.
You could try xor'ing the contents of the file with a specific value, creating an XOR-cipher, just be sure to read/write the file in binary mode. You'd have to test this out to see if this works for your purposes (it does fine with text files, and I don't see why it wouldn't work for binaries.)
Of course you have to use the same (key) value (for instance a character) to encode and decode - though you can use the same code for both of these operations.
Here's some code I recently put together which does just that:
import sys
def processData(filename, key):
with open(filename, 'rb') as inf, open(filename+'.xor', 'wb') as outf:
for line in inf:
line = ''.join([chr(ord(c)^ord(key)) for c in line])
outf.write(line)
if __name__ == '__main__':
if len(sys.argv) != 3:
print 'Usage: xor_it filename key'
print ' key = a single character'
else:
processData(sys.argv[1], sys.argv[2])
I have had success with stealthZip getting through e-mail and proxy restrictions!
However, if you do want to do it in python, you could try using pickle. Load the file in binary mode, pickle it, send it over, and unpickle it on the receiving end. I don't know how well pickle functions with binaries though.
You could also simply base64 encode the file. This will make your file larger, but has the benefit of being all ascii text (which you could then just paste in the email.)
Note this will overwrite the current file. It wouldn't be hard to change it to output to another file.
#b64.py
import base64
import sys
def help():
print """Usage: python b64.py -[de] file
-d\tdecode
-e\tencode"""
sys.exit(0)
def decode(filename):
with open(filename) as f:
bin = base64.b64decode(f.read())
with open(filename,'wb') as f:
f.write(bin)
def encode(filename):
with open(filename,'rb') as f:
text = base64.b64encode(f.read())
with open(filename,'w') as f:
f.write(text)
if len(sys.argv) != 3:
help()
if sys.argv[1] == "-d":
decode(sys.argv[2])
elif sys.argv[1] == "-e":
encode(sys.argv[2])
else:
help()
Here is my code:
# header.py
def add_header(filename):
header = '"""\nName of Project"""'
try:
f = open(filename, 'w')
except IOError:
print "Sorry could not open file, please check path"
else:
with f:
f.seek(0,0)
f.write(header)
print "Header added to", filename
if __name__ == "__main__":
filename = raw_input("Please provide path to file: ")
add_header(filename)
When I run this script (by doing python header.py), even when I provide a filename which does not exist it does not return the messages in the function. It returns nothing even when I replace the print statements with return statements. How would I show the messages in the function?
I believe you are always creating the file. Therefore, you won't see a file not there exception. It does not hurt to put a write or file open write under try except, because you might not have privileges to create the file.
I have found with statements like try except and else to test those at the Python command line, which is a very excellent place to work out cockpit error, and I'm very experienced at generating a lot of cockpit error while proving out a concept.
The fact you're using try except is very good. I just have to go review what happens when a logic flow goes through one of them. The command line is a good place to do that.
The correct course of action here is to try and read the file, if it works, read the data, then write to the file with the new data.
Writing to a file will create the file if it doesn't exist, and overwrite existing contents.
I'd also note you are using the with statement in an odd manner, consider:
try:
with open(filename, 'w') as f:
f.seek(0,0)
f.write(header)
print("Header added to", filename)
except IOError:
print("Sorry could not open file, please check path")
This way is more readable.
To see how to do this the best way possible, see user1313312's answer. My method works but isn't the best way, I'll leave it up for my explanation.
Old answer:
Now, to solve your problem, you really want to do something like this:
def add_header(filename):
header = '"""\nName of Project"""'
try:
with open(filename, 'r') as f:
data = f.read()
with open(filename, 'w') as f:
f.write(header+"\n"+data)
print("Header added to"+filename)
except IOError:
print("Sorry could not open file, please check path")
if __name__ == "__main__":
filename = raw_input("Please provide path to file: ")
add_header(filename)
As we only have the choices of writing to a file (overwriting the existing contents) and appending (at the end) we need to construct a way to prepend data. We can do this by reading the contents (which handily checks the file exists at the same time) and then writing the header followed by the contents (here I added a newline for readability).
This is a slightly modified version of Lattywares solution. Since it is not possible to append data to the beginning of a file, the whole content is read and the file is written anew including your header. By opening the file in read/write mode we can do both operations with the same file handler without releasing it. This should provide some protection against race conditions.
try:
with open(filename, 'r+') as f:
data = f.read()
f.seek(0,0)
f.write(header)
f.write(data)
#f.truncate() is not needed here as the file will always grow
print("Header added to", filename)
except IOError:
print("Sorry, could not open file for reading/writing")
this script opens a file in "w" mode (write mode),which means once the file dose not exist,it will be created. So No IOError.
I need to add a single line to the first line of a text file and it looks like the only options available to me are more lines of code than I would expect from python. Something like this:
f = open('filename','r')
temp = f.read()
f.close()
f = open('filename', 'w')
f.write("#testfirstline")
f.write(temp)
f.close()
Is there no easier way? Additionally, I see this two-handle example more often than opening a single handle for reading and writing ('r+') - why is that?
Python makes a lot of things easy and contains libraries and wrappers for a lot of common operations, but the goal is not to hide fundamental truths.
The fundamental truth you are encountering here is that you generally can't prepend data to an existing flat structure without rewriting the entire structure. This is true regardless of language.
There are ways to save a filehandle or make your code less readable, many of which are provided in other answers, but none change the fundamental operation: You must read in the existing file, then write out the data you want to prepend, followed by the existing data you read in.
By all means save yourself the filehandle, but don't go looking to pack this operation into as few lines of code as possible. In fact, never go looking for the fewest lines of code -- that's obfuscation, not programming.
I would stick with separate reads and writes, but we certainly can express each more concisely:
Python2:
with file('filename', 'r') as original: data = original.read()
with file('filename', 'w') as modified: modified.write("new first line\n" + data)
Python3:
with open('filename', 'r') as original: data = original.read()
with open('filename', 'w') as modified: modified.write("new first line\n" + data)
Note: file() function is not available in python3.
Other approach:
with open("infile") as f1:
with open("outfile", "w") as f2:
f2.write("#test firstline")
for line in f1:
f2.write(line)
or a one liner:
open("outfile", "w").write("#test firstline\n" + open("infile").read())
Thanks for the opportunity to think about this problem :)
Cheers
with open("file", "r+") as f: s = f.read(); f.seek(0); f.write("prepend\n" + s)
You can save one write call with this:
f.write('#testfirstline\n' + temp)
When using 'r+', you would have to rewind the file after reading and before writing.
Here's a 3 liner that I think is clear and flexible. It uses the list.insert function, so if you truly want to prepend to the file use l.insert(0, 'insert_str'). When I actually did this for a Python Module I am developing, I used l.insert(1, 'insert_str') because I wanted to skip the '# -- coding: utf-8 --' string at line 0. Here is the code.
f = open(file_path, 'r'); s = f.read(); f.close()
l = s.splitlines(); l.insert(0, 'insert_str'); s = '\n'.join(l)
f = open(file_path, 'w'); f.write(s); f.close()
This does the job without reading the whole file into memory, though it may not work on Windows
def prepend_line(path, line):
with open(path, 'r') as old:
os.unlink(path)
with open(path, 'w') as new:
new.write(str(line) + "\n")
shutil.copyfileobj(old, new)
One possibility is the following:
import os
open('tempfile', 'w').write('#testfirstline\n' + open('filename', 'r').read())
os.rename('tempfile', 'filename')
If you wish to prepend in the file after a specific text then you can use the function below.
def prepend_text(file, text, after=None):
''' Prepend file with given raw text '''
f_read = open(file, 'r')
buff = f_read.read()
f_read.close()
f_write = open(file, 'w')
inject_pos = 0
if after:
pattern = after
inject_pos = buff.find(pattern)+len(pattern)
f_write.write(buff[:inject_pos] + text + buff[inject_pos:])
f_write.close()
So first you open the file, read it and save it all into one string.
Then we try to find the character number in the string where the injection will happen. Then with a single write and some smart indexing of the string we can rewrite the whole file including the injected text now.
Am I not seeing something or couldn't we just use a buffer large-enough to read-in the input file in parts (instead of the whole content) and with this buffer traverse the file while it is open and keep exchanging file<->buffer contents?
This seems much more efficient (for big files especially) than reading the whole content in memory, modifying it in memory and writing it back to the same file or (even worse) a different one. Sorry that now I don't have time to implement a sample snippet, I'll get back to this later, but maybe you get the idea.
As I suggested in this answer, you can do it using the following:
def prepend_text(filename: Union[str, Path], text: str):
with fileinput.input(filename, inplace=True) as file:
for line in file:
if file.isfirstline():
print(text)
print(line, end="")
If you rewrite it like this:
with open('filename') as f:
read_data = f.read()
with open('filename', 'w') as f:
f.write("#testfirstline\n" + read_data)
It's rather short and simple.
For 'r+' the file needs to exist already.
this worked for me
def prepend(str, file):
with open(file, "r") as fr:
read = fr.read()
with open(file, "w") as fw:
fw.write(str + read)
fw.close()