As usual, create two directories for today's class. Create a
directory called lecture33
under activities, and
a directory called lab33
under labs.
I have shown you how you can trick python into reading a file by using a file as standard input. This works as a bit of a hack, but sometimes we want to actually read a true file from the system. We can even write files using Python as well
Turingscraft won't do File IO apparently, so additional in class activities! As with last weeks Turingscraft exercises, you should work on your own for this activity.
Create a program in a file called fileio.py
. The program
should read a file called in.txt that consists of a list of
integers, each on their own line. The program should write a file
called out.txt that is the same as in.txt with all
even integers removed. For example:
$ cat in.txt 1 2 3 4 5 6 $ python fileio.py $ cat out.txt 1 3 5
Many of the programs that you use on a daily basis all have some element of persistence to them. For example, Emacs can read and write text files that the user writes, or the Messages list on your phone keeps track of all the text-messages you have received. In fact, these programs would be worthless if they couldn't store this data.
Even programs that you wouldn't typically think of require a large
amount of stored data in order to accomplish their tasks. Mozilla
Firefox, for example, creates an entire directory to store the files
necessary to store the information that persists between browsing
sessions. It is located in a hidden folder in your home directory
called .mozilla/
.
In fact, if you have ever get an error opening Firefox because it claims there is already a browser instance open, you can solve the problem by removing one of these persistent files:
$ cd ~/.mozilla/firefox/<some random string of characters>.default/ $ rm lock .parentlock
Since (seemingly) all useful programs rely on files, today you will write such a program. Your program will allow the user to write and store some information using your program. The choice is up to you, but here are some ideas:
Let the user store their current list of things to do.
Allow the user to catalog their CD/DVD collection.
Let the user dictate their deepest and darkest secrets to your program. No peeking!
Let the user keep track of everywhere they have been.
Create a program called user_database.py
. This program
will allow the user to enter in their information, and have it saved
for later. This exercise is pretty open ended, but there are a few
restrictions:
Your program must read and store information that the user types
in via the input
function.
Your program should ask the user which file they would like to use for this program at start-up.
The main portion of your program will be a menu driven system that allows the users to add entries or read all entries. They should also be able to save their changes, and exit the program gracefully.
$ python3 user_database.py Please enter the file you wish to load from and save to: scotty_db Welcome to the CD collection processor! Your choices are: (A) Add an entry (R) Read all entries (E) Exit the program (S) Write collection to file Enter your choice: A Album Title: The Wall Album Artist: Pink Floyd Welcome to the CD collection processor! Your choices are: (A) Add an entry (R) Read all entries (E) Exit the program (S) Write collection to file Enter your choice: R The Wall - Pink Floyd Welcome to the CD collection processor! Your choices are: (A) Add an entry (R) Read all entries (E) Exit the program (S) Write collection to file Enter your choice: S Welcome to the CD collection processor! Your choices are: (A) Add an entry (R) Read all entries (E) Exit the program (S) Write collection to file Enter your choice: E $cat scotty_db The Wall - Pink Floyd
Your program should read from the file when the program starts, and store that information into a list. You will use that list as the local storage while the program executes.
Your program should only write to the file when the user selects save. You should write the entire contents of the in-memory list to the file at that point.
You should not save the file when the user quits the program.
You might want to make separate functions for
add_entry
, read_entries
,
read_file
, and save_file
.
add_entry
and read_entries
should take
the current database list as a parameter, read_file
and save_file
should take the file_name (a string)
as parameter. save_file
also needs the current
database list as well.
close
your file objects when you
are done with them!
As you have likely experienced, Emacs does a pretty good job of keeping up with changes you make to a file even if it does not quit gracefully. If you have seen a file with hash-tags (#) surrounding it, you likely discovered that it is an auto-save feature of the program. That is incredibly useful, so why not add that to yours?
Update your program so that it performs an auto-save of the file every 5 updates to the in-memory contents of the file. This file should have the same name as the normal file, but is surrounded in "#" characters.
When your program starts up, you should check to see if the
auto-save file exists. If it does, you should ask the user if they
want to load the backup file instead. If you import
os
, you can use the os.path.isfile
function to
determine if the file passed as a parameter exists.
$ cat scotty_db The Wall - Pink Floyd $ cat #scotty_db# The Wall - Pink Floyd Physical Graffiti - Led Zeppelin Alpocalypse - Weird Al Yankovic Incredibad - The Lonely Island Greatest Hits - Queen What a Wonderful World - Louis Armstrong $ python3 user_database.py Please enter the file you wish to load from and save to: scotty_db There is a recovery file for this database. Would you like to recover? Y Welcome to the CD collection processor! Your choices are: (A) Add an entry (R) Read all entries (E) Exit the program (S) Write collection to file Enter your choice: R The Wall - Pink Floyd Physical Graffiti - Led Zeppelin Alpocalypse - Weird Al Yankovic Incredibad - The Lonely Island Greatest Hits - Queen What a Wonderful World - Louis Armstrong ...
Cryptography can be used to make the contents of a message secret, but sometimes you want to hide that a message is even being sent. Steganography is one way to hide messages that takes advantage of our inability to perceive small changes in colors. For example the image below consists of two boxes with different colors.
The left box has the RGB values (161, 187, 150). The box on the right has the RGB values (162, 188, 151). The two boxes appear to be the same color because the RGB values are similar. A message can be hidden in an image by making small changes to the RGB values of an existing image.
A common way of modifying an image is to change only the least significant bits of the RGB values. The least significant bit of a number is the right-most bit and represents the value 20, or 1. Therefore, the most a color value will change if the least significant bit is change is 1, which the above image demonstrates as imperceptible. The following whale image, for example, has a message encoded in it.
Create a function called decode_image(ppm_file_name)
in a file called steganography.py
. The program should return
the secret message that is embedded in the specified image file. The
message is encoded as 8-bit ASCII in the least significant bit of the
image's color data. Assume that the number of color values in the
file is a factor of 8. Once you have tested your program on a simple
example, you can test it on the above whale
image.
Some things to keep in mind:
The first three lines of a PPM file specify header information for the image. You will have to skip these three lines.
Each subsequent line specifies one color value of a pixel (Red, Green, and Blue repectively). You need to extract the least significant bit of each of these values.
Once you have processed 8 color values, you will have to convert the binary sequence represented by their least significant bits into a single character. This is one character in the hidden message.
>>> image_file = open("demo.ppm", "r") >>> print(image_file.read()) P3 1 8 255 122 101 215 42 2 128 200 13 64 203 155 130 36 172 91 180 88 77 55 22 44 66 33 99 >>> print(decode_image("demo.ppm")) abc
Write a function that can embed messages into images. The function should take three parameters: a message, an input image file name, and an output image file name. It should read in the input image, modify the least significant bits of the color values to embed the message, and write the new image to the specified output file.
When you have finished, create a tar file of your lab33
directory. To create a tar file, execute the following commands:
cd ~/cs120/labs tar czvf lab33.tgz lab33/
To submit your activity, go to cseval.roanoke.edu. You should
see an available assignment called Lab Assignment 33
. Only
one of your pair should submit your activity. Make sure both partners
are listed in the header of your files.
Do not forget to email your partner today's files!