So far, we have an SMS service which automatically responds to incoming messages, and allows the keywords and messages to be edited. But our script is not perfect: whenever it stops, all changes to the database are lost. We must make our database persistent, so it is still around when we restart the script, even after turning off the phone.
To persistently save data, our phone offers a file system. This is very similar to file systems on other computers, be it Windows® or a UNIX®-like system. The main difference is that by far the most common media to store files on larger computers are hard disks, whereas your phone most likely uses memory chips, but this doesn't matter at all. The idea of the file system remains the same.
As on Windows, the file system is organized into drives with directories (folders) and subdirectores. Each file has a name which must be unique to its directory. Section * (Library) tells you more about it.
To access a file from m, module module io is used. Using this module, a function save() saving our database to a file could look as follows:
|
use io function save(table, file="table.dat") f=io.create(file); for k in keys(table) do io.writeln(f, k); io.writeln(f, table[k]) end; io.close(f) end |
Some explanations:
|
save(db); save(db, "table.dat") |
A function can have as many optional arguments as needed, provided they are the last ones. Section * (Reference) gives you the details.
|
save(db) |
the file table.dat may contain this (use a shell session to easily type the contents of a file):
|
m>type table.dat → party
The party starts at 8pm! place I am at home. mood Just don't ask. |
A function load() to read this data back in could look as follows:
|
function load(file="table.dat") table=[]; try f=io.open(file); k=io.readln(f); while k#null do table[k]=io.readln(f); k=io.readln(f) end; io.close(f) catch e by end; return table end |
This function is slightly more complicated:
|
db=load() |
To solve this problem, we could add a special separator token marking the end of a line, making load() considerably more complicated. But m offers a much simpler solution: the two functions io.readm() and io.writem() allow to write (almost) any m value directly to a file, and read it back in, all in one go. io.writem() not only writes the data, but also information about its type, the length of arrays, their keys, etc. io.readm() uses this information to reconstruct the value from the file[4].
The disadvantage is that the file written is no longer a simple text file you can edit yourself. Instead, it is a binary file highly sensitive to changes, so it is best to treat such files as a black box.
With these two functions, saving and loading becomes particularly easy:
|
use io function save(table, file="table.dat") f=io.create(file); io.writem(f, table); io.close(f) end function load(file="table.dat") try f=io.open(file); table=io.readm(f); io.close(f); return table catch e by return [] end end |