Switch branches/tags
Nothing to show
Find file
Fetching contributors…
Cannot retrieve contributors at this time
196 lines (166 sloc) 11.3 KB
<title>Lesson 10 - File I/O</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<meta name="keywords" content="civilization,civ2,civ3,civ4,civilization iii,civilization ii,civilization iv,mod,python,xml,script,install" />
<meta name="description" content="A Python and XML tutorial aimed at Civilization IV modding" />
</head><link rel="stylesheet" type="text/css" href="../../stylesheet.css" />
<body bgcolor="Teal">
<div align="center" class="SidePanel">
<div align="left" class="PaddingBig">
<div class="MenuSection">
<h2>Civilization IV Python tutorial</h2><h3>The Python Tutorial</h3>
<p>The original python tutorial</p>
<div class="MenuItem">&nbsp;<a href="">Installing Python</a></div>
<div class="MenuItem">&nbsp;<a href="">Very Simple Programs</a></div>
<div class="MenuItem">&nbsp;<a href="">Variables, Scripts</a></div>
<div class="MenuItem">&nbsp;<a href="">Loops, Conditionals</a></div>
<div class="MenuItem">&nbsp;<a href="">Functions</a></div>
<div class="MenuItem">&nbsp;<a href="">Tuples, Lists, Dictionaries</a></div>
<div class="MenuItem">&nbsp;<a href="">for Loop</a></div>
<div class="MenuItem">&nbsp;<a href="">Classes</a></div>
<div class="MenuItem">&nbsp;<a href="">Importing Modules</a></div>
<div class="MenuItem">&nbsp;<a href="">File I/O</a></div>
<div class="MenuItem">&nbsp;<a href="">Error Handling</a></div>
<h3>The Civ4 Programming Tutorial</h3>
<p>All new Civ4 programming tutorial</p>
<div class="MenuItem">&nbsp;<a href="">Lesson 1 (not released)</a></div>
<br /><br /></div></div>
<div align="center" class="TextPanel">
<div align="left" class="Padding"><h2>File I/O</h2>
<p>Last lesson we learnt how to load external code into our program. Without any introduction (like what I usually have), let's delve into file input and output with normal text files, and later the saving and restoring of instances of classes. (Wow, our lingo power has improved greatly!)</p>
<h3>Opening a file</h3>
<p>To open a text file you use, well, the open() function. Seems sensible. You pass certain parameters to open() to tell it in which way the file should be opened - 'r' for read only, 'w' for writing only (if there is an old file, it will be written over), 'a' for appending (adding things on to the end of the file) and 'r+' for both reading and writing. But less talk, lets open a file for reading (you can do this in your python idle mode). Open a normal text file. We will then print out what we read inside the file:</p>
<div align="center">
<div align="center" class="CodeTitle">Code Example 1 - Opening a file</div>
<div align="left" class="CodeBody">
openfile = open('pathtofile', 'r')
</div><p>That was interesting. You'll notice a lot of '\n' symbols. These represent newlines (where you pressed enter to start a new line). The text is completely unformatted, but if you were to pass the output of <tt></tt> to print (by typing <tt>print</tt>) it would be nicely formatted.</p>
<h3>Seek and You Shall Find</h3>
<p>Did you try typing in <tt>print</tt>? Did it fail? It likely did, and reason is because the 'cursor' has changed it's place. Cursor? What cursor? Well, a cursor that you really cannot see, but still a cursor. This invisible cursor tells the read function (and many other I/O functions) where to start from. To set where the cursor is, you use the seek() function. It is used in the form <tt>seek(offset, whence)</tt>.</p>
<p><b>whence</b> is optional, and determines where to seek from. If whence is 0, the bytes/letters are counted from the beginning. If it is 1, the bytes are counted from the current cursor position. If it is 2, then the bytes are counted from the end of the file. If nothing is put there, 0 is assumed.</p>
<p><b>offset</b> decribes how far from whence that the cursor moves. for example:</p>
<ul><li><tt>,0)</tt> would move the cursor to 45 bytes/letters after the beginning of the file.</li>
<li><tt>,1)</tt> would move the cursor to 10 bytes/letters after the current cursor position.</li>
<li><tt>,2)</tt> would move the cursor to 77 bytes/letters before the end of the file (notice the - before the 77)</li>
</ul><p>Try it out now. Use <tt></tt> to go to any spot in the file and then try typing print <tt></tt>. It will print from the spot you seeked to. But realise that <tt></tt> moves the cursor to the end of the file - you will have to seek again.</p>
<h3>Other I/O Functions</h3>
<p>There are many other functions that help you with dealing with files. They have many uses that empower you to do more, and make the things you can do easier. Let's have a look at <tt>tell()</tt>, <tt>readline()</tt>, <tt>readlines()</tt>, <tt>write()</tt> and <tt>close()</tt>.</p>
<p><tt>tell()</tt> returns where the cursor is in the file. It has no parameters, just type it in (like what the example below will show). This is infinitely useful, for knowing what you are refering to, where it is, and simple control of the cursor. To use it, type <tt>fileobjectname.tell()</tt> - where <tt>fileobjectname</tt> is the name of the file object you created when you opened the file (in <tt>openfile = open('pathtofile', 'r')</tt> the file object name is <tt>openfile</tt>).</p>
<p><tt>readline()</tt> reads from where the cursor is till the end of the line. Remember that the end of the line isn't the edge of your screen - the line ends when you press enter to create a new line. This is useful for things like reading a log of events, or going through something progressively to process it. There are no parameters you have to pass to readline(), though you can optionally tell it the maximum number of bytes/letters to read by putting a number in the brackets. Use it with <tt>fileobjectname.readline()</tt>.</p>
<p><tt>readlines()</tt> is much like <tt>readline()</tt>, however <tt>readlines()</tt> reads all the lines from the cursor onwards, and returns a list, with each list element holding a line of code. Use it with <tt>fileobjectname.readlines()</tt>. For example, if you had the text file:</p>
<div align="center">
<div align="center" class="CodeTitle">Code Example 2 - example text file</div>
<div align="left" class="CodeBody">
Line 1
Line 3
Line 4
Line 6
</div><p>then the returned list from <tt>readlines()</tt> would be:</p>
<div align="center">
<div align="center" class="CodeTitle">Table 1 - resulting list from readlines</div>
<table class="TableBody">
<td class="TableContent" width="20%"><b>Index</b></td>
<td class="TableContent" width="80%"><b>Value</b></td>
<td class="TableContent">0</td>
<td class="TableContent">'Line 1'</td>
<td class="TableContent">1</td>
<td class="TableContent">''</td>
<td class="TableContent">2</td>
<td class="TableContent">'Line 3'</td>
<td class="TableContent">3</td>
<td class="TableContent">'Line 4'</td>
<td class="TableContent">4</td>
<td class="TableContent">''</td>
<td class="TableContent">5</td>
<td class="TableContent">'Line 6'</td>
</div><br /><p>The <tt>write()</tt> function, writes to the file. How did you guess??? It writes from where the cursor is, and overwrites text in front of it - like in MS Word, where you press 'insert' and it writes over the top of old text. To utilise this most purposeful function, put a string between the brackets to write e.g. <tt>fileobjectname.write('this is a string')</tt>.</p>
<p><tt>close</tt>, you may figure, closes the file so that you can no longer read or write to it until you reopen in again. Simple enough. To use, you would write <tt>fileobjectname.close()</tt>. Simple!</p>
<p>In Python idle mode, open up a test file (or create a new one...) and play around with these functions. You can do some simple (and very inconvenient) text editing.</p>
<h3>Mmm, Pickles</h3>
<p>Pickles, in Python, are to be eaten. Their flavour is just to good to let programmers leave them in the fridge.</p>
<p>Ok, just joking there. Pickles, in Python, are objects saved to a file. An object in this case could be a variables, instance of a class, or a list, dictionary, or tuple. Other things can also be pickled, but with limits. The object can then be restored, or unpickled, later on. In other words, you are 'saving' your objects.</p>
<p>So how do we pickle? With the <tt>dump()</tt> function, which is inside the pickle module - so at the beginning of your program you will have to write <tt>import pickle</tt>. Simple enough? Then open an empty file, and use <tt>pickle.dump()</tt> to drop the object into that file. Let's try that:</p>
<div align="center">
<div align="center" class="CodeTitle">Code Example 3 -</div>
<div align="left" class="CodeBody">
# import the pickle module
import pickle
# lets create something to be pickled
# How about a list?
picklelist = ['one',2,'three','four',5,'can you count?']
# now create a file
# replace filename with the file you want to create
file = open('filename', 'w')
# now let's pickle picklelist
# close the file, and your pickling is complete
</div><p>The code to do this is laid out like <tt>pickle.load(object_to_pickle, file_object)</tt> where:</p>
<ul><li><tt>object_to_pickle</tt> is the object you want to pickle (i.e. save it to file)</li>
<li><tt>file_object</tt> is the file object you want to write to (in this case, the file object is 'file')</li>
</ul><p>After you close the file, open it in notepad and look at what you see. Along with some other gibblygook, you will see bits of the list we created.</p>
<p>Now to re-open, or unpickle, your file. to use this, we would use <tt>pickle.load()</tt>:</p>
<div align="center">
<div align="center" class="CodeTitle">Code Example 4 -</div>
<div align="left" class="CodeBody">
### unpickle file
# import the pickle module
import pickle
# now open a file for reading
# replace filename with the path to the file you created in
unpicklefile = open('filename', 'r')
# now load the list that we pickled into a new object
unpickledlist = pickle.load(unpicklefile)
# close the file, just for safety
# Try out using the list
for item in unpickledlist:
print item
</div><p>Nifty, eh?</p>
<p>Of course, the limitation above is that we can only put in one object to a file. We could get around this by putting lots of picklable objects in a list or dictionary, and then pickling that list or dictionary. This is the quickest and easiest way, but you can do some pretty advanced stuff if you have advanced knowledge of <tt>pickle</tt>.</p>
<p>Which we won't cover.</p>
<p>Which ends this lesson.</p>
<p>Thanks to all,</p>