A alguns dias houve um tópico interessante na lista de discussão sobre plua no yahoo groups (a lista é fechada, por isso passei um link alternativo).O sujeito Jimmy Joe Jack, disse que queria fazer algo para seu palm com plua, mas não tinha muito tempo para aprender e por isso não queria ler a documentação toda (que é pequena, mas longe de ser fácil), pediu que enviássemos alguns exemplos.
Foi quando Berkant Atay respondeu, mandando um exemplo que fazia algo quando apertava um botão, e na sequecia mandou exemplos de como trabalhar com arquivos, stream e data bases.
Aproveitei a deixa para também aprender como isso afinal funcionava (obrigado Berkant). Deixo agora neste post o que aprendi com meu primeiro exemplo gravando informações em arquivos.
Fazendo a leitura de um arquivo de banco de dados
Plua disponibiliza uma série de funções, veja na documentação lá onde diz "Database I/O functions". Vamos a um trecho de códigos que fica mais fácil.
-- open in read mode
file,NumRegs = io.open("db:/AgesNames", "r+")
-- define a variable
returnData = {}
-- Atention!in DB file, the index begin in 0 (zero)
-- but in table, array..the index begin in 1 (one)
for i=0,NumRegs-1 do
-- open data from index
file:openrec(i) -- begin in zero
-- read this data
data = file:read("*a")
temp = bin.unpack("SB",data)
-- add this data to returning variable
returnData[i+1] = temp[2].."\t"..temp[1]
end
file:close()
Logo no início eu abro o arquivo com "r+" através do "protocolo" "db", disse que o nome de meu banco de dados é "AgesNames". Assim como em outras linguagens há modos de abrir aquivos. vejamos (tradução livre do manual):
- "r": Abre para leitura. Se o arquivo não existe não é feito nada, apenas da erro.
- "r+": abre/cria para leitura/escrita. Se o arquivo já existe ele é preservado, caso contrário é criado. O conteúdo do arquivo é mantido.
- "w": abre/cria para escrita. Se o arquivo existe ele é truncado (o conteúdo dele é apagado), se não existe o arquivo é criado.
- "a": abre/cria para escrita. Se o arquivo existe ele é preservado, o ponteiro aponta para o fim do arquivo, se o arquivo não existe ele é criado.
Em seguida fazemos um laço da primeira a última linha de dados do arquivo. Atenção que o primeiro índice de um arquivo é 0 (zero), enquanto que as tables (arrays, vectors) em Lua iniciam no índice 1.
Você deve ter notado que no "read" também tem uma letra, pois bem, veja o que o manual da Lua diz:
- "*n": lê um número; este é o único formato que retorna um número ao invés de uma cadeia.
- "*a": lê o arquivo inteiro, iniciando na posição corrente. Quando está no final do arquivo, retorna a cadeia vazia.
- "*l": lê a próxima linha (pulando o fim de linha), retornando nil ao final do arquivo. Este é o formato padrão.
- number: lê uma cadeia até este número de caracteres, retornando nil ao final do arquivo. Se o número fornecido é zero, a função não lê nada e retorna uma cadeia vazia ou nil quando está no fim do arquivo.
No caso deste programa temos duas colunas "name" e "age", o primeiro uma string e o segundo um número inteiro positivo. Por causa dessas duas colunas é que temos duas letras dentro do bin.unpack, uma letra dizendo que tipo de dados é cada coluna. Veja no manual da Plua o que diz de cada um dos tipos (tradução livre).
- B=8 bits integer positivos e negativos;
- W=big endian 16 bits inteiros positivos e negativos;
- L=big endian 32 bits inteiros positivos e negativos;
- F=big endian 32 bits float;
- D=big endian 64 bits double;
- S= String variável, termina com um ASCII null.
A última parte do código, eu concateno as duas colunas de dados em uma, e armazeno então uma matriz em um vector, que depois vai ser usado como fonte de dados para uma gui.list.
Gravando em um arquivo
Agora que você já sabe o que cada coisa significa, a gravação é fácil. Primeiro eu pego os dados dos meus campos da interface (gui.field), coloco isso em uma table (vector), dou um "bin.pack", aloco o espaço necessário para aqueles dados e mando gravar, e claro, fecho o arquivo.
-- retrive values from fieldsO desenho da interface, e como saber que o botão "add" foi pressionado
name = gui.gettext(dataName)
age = gui.gettext(dataAge)
dataToWrite = {name,age}
-- open for write the data base file
file = io.open("db:/AgesNames","w")
-- encode, acording the data tyes
packed = bin.pack("SB",dataToWrite)
-- how many size is this data?
index = file:createrec(string.len(packed))
-- alloc this size on file
file:openrec(index)
-- finaly write
file:write(packed)
-- and close file
file:close()
Tenha bons costumes, sempre que inicia a desenhar uma tela, destrua o que já há, fica mais fácil de controlar. Em seguida mando limpar a tela.
gui.destroy()
screen.clear()
gui.title("Simple read and write")
gui.nl();
gui.label("Name:");
dataName = gui.field(1,10,20)
gui.label("Age:");
dataAge = gui.field(1,3,3)
gui.control{type="button", text="Add", handler=saveData}
gui.nl()
data = read()
gui.list(10,32,data)
Digo qual é o título, vou uma linha para baixo (gui.nl) e adiciono as labels e os fields. O detalhe está no botão, em que associo ele a função "saveData" que é o código de gravação do logo acima.
Nova linha, e a função que lê o banco de dados traz os dados em "data" que é atribuido a "gui.list". Quando um registro é gravado, perceba que eu chamo novamente a função que redesenha a interface e faz novamente então a leitura dos dados.
Código na íntegra abaixo:
-- this file write and read data using a palm dbÉ isso amigos, até a próxima, agradescimento especial a Berkant Atay, ilustre desconhecido.
function read()
-- open in read mode
file,NumRegs = io.open("db:/AgesNames", "r+")
-- define a variable
returnData = {}
-- Atention!in DB file, the index begin in 0 (zero)
-- but in table, array..the index begin in 1 (one)
for i=0,NumRegs-1 do
-- open data from index
file:openrec(i) -- begin in zero
-- read this data
data = file:read("*a")
temp = bin.unpack("SB",data)
-- add this data to returning variable
returnData[i+1] = temp[2].."\t"..temp[1]
end
file:close()
-- if are empty, return this information
if(returnData == nil) then
returnData[1] = "No data writed"
end
return returnData
end
function saveData(e, id, arg)
-- retrive values from fields
name = gui.gettext(dataName)
age = gui.gettext(dataAge)
dataToWrite = {name,age}
-- open for write the data base file
file = io.open("db:/AgesNames","w")
-- encode, acording the data tyes
packed = bin.pack("SB",dataToWrite)
-- how many size is this data?
index = file:createrec(string.len(packed))
-- alloc this size on file
file:openrec(index)
-- finaly write
file:write(packed)
-- and close file
file:close()
drawGui()
end
function drawGui()
gui.destroy()
screen.clear()
gui.title("Simple read and write")
gui.nl();
gui.label("Name:");
dataName = gui.field(1,10,20)
gui.label("Age:");
dataAge = gui.field(1,3,3)
gui.control{type="button", text="Add", handler=saveData}
gui.nl()
data = read()
gui.list(10,32,data)
end
drawGui()
gui.main()
"I'm learning English, so it is possible that I have written incorrectly. If so, please tell me. Thanks!"
ResponderExcluirGreat article: translated it via Google Translate: http://google.com/translate