-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathch17.html
More file actions
177 lines (174 loc) · 9.83 KB
/
Copy pathch17.html
File metadata and controls
177 lines (174 loc) · 9.83 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
<!doctype html>
<html>
<head>
<meta http-equiv="content-type" content="text/html; charset=utf-8">
<style type="text/css">
td, th { border: 1px solid #c3c3c3; padding: 0 3px 0 3px; }
table { border-collapse: collapse; }
img { max-width: 100%; }
</style>
<meta name="generator" content="ReText 7.2.3">
<title>ch17</title>
<style type="text/css">
</style>
</head>
<body>
<p><a href="ch16.html">Previous</a> <a href="index.html">Index</a> <a href="ch18.html">Next</a></p>
<hr>
<h1>17 - File input/output</h1>
<h4>Table of Contents</h4>
<ul>
<li><a href="#17.1">17.1 Opening a file channel</a></li>
<li><a href="#17.2">17.2 Closing a file channel</a></li>
<li><a href="#17.3">17.3 Reading from a file</a></li>
<li><a href="#17.4">17.4 Writing to a file</a></li>
<li><a href="#17.5">17.5 Readable/writable files</a></li>
<li><a href="#17.6">17.6 Non-text files</a></li>
<li><a href="#17.7">17.7 Using OPEN with expressions</a></li>
<li><a href="#17.8">17.8 File pointers</a></li>
</ul>
<hr>
<p>Axmud stores its data in a variety of data files. Your Axbasic scripts can create their own files, completely separate from the ones used by Axmud.</p>
<p>You can use these files to store data. Later on, you can read the contents of the files back into memory.</p>
<p>You can also create simple text files. You might want to create some kind of logfile, for example.</p>
<p>Axbasic creates files in the same directory (folder) as the Axbasic script itself. By default, that's the <strong>scripts</strong> sub-directory inside the main Axmud data directory.</p>
<h2><a name="17.1">17.1 Opening a file channel</a></h2>
<p>When we want to read from or write to a file, we create a <em>file channel</em>.</p>
<p>A channel is just a way for Axbasic to communicate with the operating system. The complexities of these communications are handled invisibly on your behalf.</p>
<p>You can create a new channel with a single OPEN statement.</p>
<pre><code> OPEN #1: NAME "myfile.txt"
</code></pre>
<p>This statement contains four parts:</p>
<ul>
<li>The keyword OPEN</li>
<li>A channel number</li>
<li>The keyword NAME</li>
<li>The name of the file to open</li>
</ul>
<p>Every channel has a number, so if you want to manipulate multiple files simultaneously, you can open as many channels as you need (up to a maximum of 25). Each individual channel handles a single file. You can't open multiple channels to the same file.</p>
<h2><a name="17.2">17.2 Closing a file channel</a></h2>
<p>When the Axbasic script stops running, any file channels are automatically closed. Still, it's good practice to close the channel yourself as soon as you're finished with it.</p>
<pre><code> CLOSE #1
</code></pre>
<h2><a name="17.3">17.3 Reading from a file</a></h2>
<p>Once the channel is open, you can read data from a file, one line at a time. This is done with an ordinary INPUT statement, but one that uses a new format.</p>
<pre><code> INPUT #1: value$
</code></pre>
<p>Because we always specify the channel number, we could easily read a single line from each of three files.</p>
<pre><code> DIM numbers (3)
OPEN #1: NAME "myfile1.txt"
OPEN #2: NAME "myfile2.txt"
OPEN #3: NAME "myfile3.txt"
INPUT #1: numbers (1)
INPUT #2: numbers (2)
INPUT #3: numbers (3)
</code></pre>
<p>Unless you're <em>absolutely certain</em> that the file contains only numeric values, you should use string variables, not numeric variables. Reading a string into a numeric variable will cause an error. (You can convert string variables into numeric variables later, if need be.)</p>
<p>You can read several values at a time. This example reads three lines from the file, one after the other.</p>
<pre><code> INPUT #1: name$, address$, postcode$
</code></pre>
<p>Here's a complete example of a script that reads the contents of a file that we know contains 10 values.</p>
<pre><code> ! Read ten values
DIM numbers (10)
OPEN #1: NAME "myfile.txt"
FOR a = 1 TO 10
INPUT #1: numbers (a)
PRINT numbers (a)
NEXT a
CLOSE #1
END
</code></pre>
<p>If you run this script now, Axmud will complain that the file doesn't exist, so let's talk about saving data.</p>
<h2><a name="17.4">17.4 Writing to a file</a></h2>
<p>When Axbasic writes to a file, it makes some assumptions. For example, it assumes that the file already exists. It also assumes that new lines should be added to the end of the file, <em>after</em> any lines that already exist there.</p>
<p>The first step, then, is to tell Axbasic to create a file, if one doesn't already exist. We do that with CREATE NEWOLD.</p>
<pre><code> OPEN #1: NAME "myfile.txt", CREATE NEWOLD
</code></pre>
<p>You could also have used CREATE NEW. If the file already exists, you'll see an error; otherwise a new file is created.</p>
<p>The third option is CREATE OLD. If the file doesn't already exist, you'll see an error; otherwise the existing file is opened. (This is the default behaviour, so using CREATE OLD is the same as not using CREATE at all.)</p>
<p>Once the channel is open, you can write data to the file, one line at a time. This is done using an ordinary PRINT statement, using the same new format.</p>
<pre><code> PRINT #1: value$
</code></pre>
<p>This script creates a data file that the previous Section's script can read.</p>
<pre><code> ! Write ten values
OPEN #1: NAME "myfile.txt", CREATE NEWOLD
FOR a = 1 TO 10
PRINT #1: a
NEXT a
CLOSE #1
END
</code></pre>
<p>If you run the script several times, it will keep adding more text to the existing file. The solution is to ERASE the file before PRINTing anything to it.</p>
<pre><code> ! Write ten values
OPEN #1: NAME "myfile.txt", CREATE NEWOLD
ERASE #1
FOR a = 1 TO 10
PRINT #1: a
NEXT a
CLOSE #1
END
</code></pre>
<p>If you want to write a partial line of text, you can use PRINT statements with commas and semicolons, just as if you were PRINTing something to the main window. The following script writes a single line of text.</p>
<pre><code> ! Write a single line of text
OPEN #1: NAME "myfile.txt", CREATE NEWOLD
ERASE #1
PRINT #1: "Going ";
PRINT #1: "going ";
PRINT #1: "gone!"
CLOSE #1
END
</code></pre>
<h2><a name="17.5">17.5 Readable/writable files</a></h2>
<p>When you open a file channel, Axbasic is able to both read and write to that file; in other words, you can use a combination of PRINT and INPUT statements, one after the other.</p>
<p>This probably isn't the behaviour you want, so it's a good idea to specify whether you want the file to be readable or writable.</p>
<p>To make a file readable, use ACCESS INPUT. You'll be able to INPUT data from that file, but not PRINT to it.</p>
<pre><code> OPEN #1: NAME "myfile.txt", CREATE NEWOLD, ACCESS OUTPUT
</code></pre>
<p>To make a file writable, use ACCESS OUTPUT. You'll be able to PRINT data to that file, but not INPUT anything from it.</p>
<pre><code> OPEN #1: NAME "myfile.txt", CREATE NEWOLD, ACCESS INPUT
</code></pre>
<p>To do both at the same tiume, use ACCESS OUTIN. (This is the default behaviour, so using ACCESS OUTIN is the same as not using ACCESS at all.)</p>
<pre><code> OPEN #1: NAME "myfile.txt", CREATE NEWOLD, ACCESS OUTIN
</code></pre>
<h2><a name="17.6">17.6 Non-text files</a></h2>
<p>Axbasic can only write text files. True BASIC can write other kinds of files. A True BASIC script might include the following line, which specifies that a text file should be opened:</p>
<pre><code> OPEN #1: NAME "myfile.txt", ORGANIZATION TEXT
</code></pre>
<p>Axbasic ignores ORGANIZATION TEXT and its abbreviation, ORG TEXT, if the script includes them.</p>
<h2><a name="17.7">17.7 Using OPEN with expressions</a></h2>
<p>The NEWOLD in CREATE NEWOLD can be replaced by an expression. (Replacing a keyword with an expression is usually not allowed, but on this occasion it is permitted.)</p>
<pre><code> LET option$ = "NEWOLD"
OPEN #1: NAME "myfile.txt", CREATE option$
</code></pre>
<p>The same applies to ACCESS, ORGANIZATION and ORG, all of which can be followed either by a keyword or an expression. The expression should evaluate to a value that's the same as the expected keyword. This might be useful if you've written a subroutine to handle all of your file input/output.</p>
<pre><code> ! A subroutine that opens a channel
! using expressions, not keywords
SUB OpenFile(file$, cr$, acc$)
OPEN #1: NAME file$, CREATE cr$, ACCESS acc$
END SUB
</code></pre>
<p>In an OPEN statement, CREATE, ACCESS, ORGANIZATION and ORG can appear in any order (but NAME must come first).</p>
<h2><a name="17.8">17.8 File pointers</a></h2>
<p>The pointer is the position in a file at which Axbasic reads or writes data.</p>
<p>When a file is opened for reading (only), the pointer is initially at the beginning of the file. The first item of data read is the first line of the file.</p>
<p>When a file is opened for writing, or for both reading and writing, the pointer is initially at the end of the file. The first item of data written is added to the end of the file.</p>
<p>You can use a RESET statement to move the pointer to the beginning or the end of the file.</p>
<pre><code> RESET #1: BEGIN
RESET #1: END
</code></pre>
<p>Here's a practical example.</p>
<pre><code> ! Open a file for writing
OPEN #1: NAME "output.txt", CREATE NEWOLD, ACCESS OUTPUT
PRINT #1: "This is added to the end of the file"
! Move the pointer
RESET #1: BEGIN
PRINT #1: "This is added to the beginning of the file"
CLOSE #1
END
</code></pre>
<p>While reading a file, you can use the <strong>Eof ()</strong> function - short for <em>end of file</em> - to test whether the pointer has reached the end of the file, or not.</p>
<p><strong>Eof ()</strong> returns 1 if the file channel is still open, and if the pointer is at the end of the file; otherwise it returns 0.</p>
<hr>
<p><a href="ch16.html">Previous</a> <a href="index.html">Index</a> <a href="ch18.html">Next</a></p>
</body>
</html>