Desenvolvendo em BREW - Parte 3 – Etapa 02
Arquivos em BREW: as interfaces IFile e IFileMgr
A primeira solução para persistência de dados em BREW que apresentaremos é a API de manipulação de arquivos. Essa API provê, assim como a maioria das linguagens de programação, funções que permitem leitura e escrita de dados não estruturados em formato binário e texto. Ela é bem semelhante à API encontrada na biblioteca stdio.h, da linguagem C, com funcionalidades de acesso seqüencial e aleatório a arquivos.
Como nesse caso o desenvolvedor não possui dados estruturados, fica a cargo dele toda a gerência e manipulação desses dados.
A API de manipulação de arquivos é composta principalmente pelas interfaces IFile e IFileMgr. A interface IFileMgr permite o gerenciamento de arquivos e diretórios, enquanto a interface IFile permite a navegação e atualização do conteúdo de um arquivo.
Sendo assim, para a criação de uma instância de IFile é necessário que exista uma instância de IFileMgr, que por sua vez é criada pelo método ISHELL_CreateInstance(), utilizando o AEECLSID_FILEMGR como ClassID. Um ponteiro para IFile pode ser acessado pelo método IFILEMGR_OpenFile(), que abre um arquivo para criação, leitura, escrita ou acréscimo de conteúdo. É importante saber que nomes de arquivos não são case sensitive e não podem ultrapassar o limite de caracteres definido pela constante AEE_MAX_FILE_NAME (cujo valor é 64, porém, no emulador é aumentado para 256 devido ao tamanho do caminho de diretórios do arquivo em questão). Para ter acesso às funções desta API, você deve incluir o arquivo de cabeçalho AEEFILE.h em seu código.
Na Tabela 1 estão descritas as principais funções da interface IFileMgr.
Tabela 1. Funções da interface IFileMgr
|
Protótipo |
Parâmetros |
Retorno |
|
IFile * IFILEMGR_OpenFile (IFileMgr * pIFileMgr, const char * pszFile, OpenFile mode)
|
· pIFileMgr - ponteiro para o objeto IFileMgr · pszFile – nome do arquivo a ser aberto · mode – modo de abertura, que pode ser o _OFM_READ, apenas para leitura de um arquivo já existente; o _OFM_READWRITE, leitura e escrita em um arquivo já existente; o _OFM_APPEND, igual ao anterior, porém com o ponteiro de arquivo é apontado para o final; o _OFM_CREATE, cria um novo arquivo. |
Retorna um ponteiro para IFile correspondente ao arquivo a ser aberto. |
|
uint32 IFileMgr_GetFreeSpace(IFileMgr * pIFileMgr, uint32 * pdwTotal) |
· pIFileMgr – ponteiro para objeto IFileMgr; · pdwTotal – ponteiro para variável que armazenará o número total de bytes do sistema de arquivos quando esta função retornar.
|
Retorna a quantidade de bytes disponíveis no sistema de arquivos. |
|
int IFILEMGR_GetInfo (IFileMgr * pIFileMgr, const char * pszName, FileInfo * pInfo) |
· pIFileMgr – ponteiro para objeto IFileMgr; · pszFile – nome do arquivo aberto; · pInfo – ponteiro para uma estrutura FileInfo que receberá as informações sobre o arquivo quando esta função retornar. |
Retorna informação de atributos de arquivos, data de criação e tamanho. Pode retornar SUCCESSFUL ou EFAILED, para indicar sucesso ou falha na execução da função. |
|
int IFILEMGR_MkDir (IFileMgr * pIFileMgr, const char * pszDir) |
· pIFileMgr – ponteiro para objeto IFileMgr; · pszDir – nome do diretório a ser criado. |
Cria um novo diretório. Pode retornar SUCCESSFUL ou EFAILED, para indicar sucesso ou falha na execução da função. |
|
uint32 IFILEMGR_Release (IBase * pIBase) |
· pIFileMgr – ponteiro para objeto IFileMgr; |
Libera o objeto IFileMgr da memória. |
|
int IFILEMGR_Remove (IFileMgr * pIFileMgr, const char * pszName) |
· pIFileMgr – ponteiro para objeto IFileMgr; · pszFile – nome do arquivo aberto; |
Remove um arquivo. Pode retornar SUCCESSFUL ou EFAILED, para indicar sucesso ou falha na execução da função. |
|
int IFILEMGR_RmDir (IFileMgr * pIFileMgr, const char * pszDir) |
· pIFileMgr – ponteiro para objeto IFileMgr; · pszDir – nome do diretório. |
Remove um diretório. Pode retornar SUCCESSFUL ou EFAILED, para indicar sucesso ou falha na execução da função. |
|
int IFILEMGR_Test (IFileMgr * pIFileMgr, const char * pszName) |
· pIFileMgr – ponteiro para objeto IFileMgr; · pszName – nome do arquivo ou diretório. |
Verifica se um arquivo ou diretório já existe. Pode retornar SUCCESSFUL ou EFAILED, para indicar sucesso ou falha na execução da função. |
Na Tabela 2 estão descritas as principais funções da interface IFile.
Tabela 2. Funções da interface IFile
|
Protótipo |
Parâmetros |
Retorno |
|
int32 IFILE_Read (IFile * pIFile, void * pBuffer, uint32 dwCount) |
· pIFile – ponteiro para objeto IFile; · pBuffer – ponteiro para buffer onde o dado lido será armazenado; · dwCount – quantidade de bytes a serem lidos do arquivo. |
Lê dwCount bytes de um arquivo. Retorna o número de bytes lidos ou zero, em caso de erro. |
|
uint32 IFILE_Release (IFile * pIFile) |
· pIFile – ponteiro para objeto IFile;
|
Fecha um arquivo |
|
uint32 IFILE_Seek (IFile * pIFile, FileSeekType seekType, int32 moveDistance) |
· pIFile – ponteiro para objeto IFile; · seekType – ponto de referência: o _SEEK_CURRENT – ponto corrente o _SEEK_START – início do arquivo o _SEEK_END – fim do arquivo · moveDistance – distância a percorrer |
Move o ponteiro de arquivo para um ponto qualquer do arquivo. |
|
uint32 IFILE_Write (IFile * pIFile, PACKED const void * pBuffer, uint32 dwCount) |
· pIFile – ponteiro para objeto IFile; · pBuffer – ponteiro para buffer de onde o dado a ser escrito será lido; · dwCount – quantidade de bytes a serem escritos no arquivo. |
Escreve dwCount bytes em um arquivo. Retorna o número de bytes escritos ou zero, em caso de erro. |
Em geral, os passos seguidos para usar a API de arquivos são:
· Criação da instância de IFileMgr através de ISHELL_CreateInstance();
· Criação ou abertura de um IFile através de IFILEMGR_OpenFile();
· Navegação, leitura, escrita, criação e remoção de arquivos e/ou diretórios;
· Liberação da instância de IFile através de IFILE_Release();
· Liberação da instância de IFileMgr através de IFILEMRG_Release().
Banco de dados em BREW
A implementação de registros em BREW permite criar, remover e alterar tabelas e registros. Como afirmamos anteriormente, cada registro pode conter um ou mais campos. Quando uma tabela é criada, são gerados automaticamente dois arquivos binários, um que armazenará o conteúdo e um arquivo de índices que permite que os dados sejam acessados corretamente. Estes arquivos, porém, não devem ser acessados diretamente pelo usuário. Este acesso deve ser feito através do uso das funções de três interfaces: IDBMgr, para gerenciar tabelas; IDatabase, para navegar dentro de uma tabela e acessar os registros; e IDBRecord para navegar dentro de um registro e acessar os seus campos. Para acessar esta API, você deve incluir o arquivo de cabeçalho AEEDB.h. Assim como na criação de IFileMgr, a criação de um ponteiro para IDBMgr é feita através de uma chamada a ISHELL_CreateInstance() utilizando o AEECLSID_DBMGR como ClassID. Para liberar a instância, o método IDBMGR_Release() deve ser chamado. Na Tabela 3, temos as principais funções da interface IDBMgr.
Tabela 3. Funções da interface IDBMgr
|
Protótipo |
Parâmetros |
Retorno |
|
IDatabase * IDBMgr_OpenDatabase ( IDBMgr * pIDBMgr, const char * pszFile, boolean bCreate) |
· pIDBMgr - ponteiro para objeto IDBMgr · pszFile – nome do banco a ser aberto · bCreate – determina se o banco deve ser criado caso o banco ainda não exista.
|
Retorna NULL se o banco já estiver aberto. Caso contrário, retorna um ponteiro para o banco. Caso o banco tenha sido criado, esta função cria um banco vazio. |
|
uint32 IDBMGR_Release (IBase * pIBase) |
· pIBase – ponteiro para objeto IBase; |
Libera o objeto IDBMgr da memória. |
|
int IDBMgr_Remove (IDBMgr * pIDBMgr, const char * pszFile)
|
· pIDBMgr - ponteiro para objeto IDBMgr · pszFile – nome do banco a ser removido
|
Remove do sistema de arquivos o banco especificado por pszFile. Pode retornar SUCCESSFUL ou EBADFILENAME caso o banco não seja encontrado. |
A criação ou abertura de uma tabela IDatabase é feita de acordo com a chamada ao método IDBMGR_OpenDatabase(). Ao fim do seu uso, a tabela deve ser fechada com o método IDATABASE_Release(). Esta interface permite acesso direto a um registro através do seu ID único ou de forma iterativa, percorrendo todos os registros. Para a criação de um novo registro faz-se uso da função IDATABASE_CreateRecord() que retorna um ponteiro para IDBRecord (esse ponteiro deve ser liberado pelo método IDBRECORD_Release()). Para cada registro criado, é automaticamente gerado um identificador único para o mesmo. Registros podem possuir um ou mais campos, cada um definido pela estrutura AEEDBField (ver Listagem 1).
Listagem 1. Estrutura AEEDBField
001 typedef structure
002 {
003 AEEDBFieldType fType;
004 AEEDBFieldName fName;
005 uint16 wDataLen;
006 void * pBuffer;
007 } AEEDBField;
Uma estrutura AEEDBField possui os seguintes elementos:
· fType – o tipo de dado do campo, que pode ser um dos valores da enumeração AEEDBFieldType:
o AEEDB_FT_BYTE – equivalente ao tipo byte;
o AEEDB_FT_WORD – equivalente ao tipo int16 ou uint16 (inteiros de 16 bits com e sem sinal);
o AEEDB_FT_DWORD – equivalente ao tipo int32 ou uint32 (inteiros de 32 bits com e sem sinal);
o AEEDB_FT_STRING – equivalente a uma string terminada em ‘\0’ com caracteres do tipo AECHAR;
o AEEDB_FT_BINARY – equivalente a um bloco binário de bytes;
o AEEDB_FT_BITMAP – equivalente a um Windows Bitmap.
· fName – descreve o conteúdo do campo. É possível usar os valores da enumeração AEEDBFieldName (ver documentação da API BREW) ou criar uma enumeração que garanta a atribuição de um valor único inteiro;
· wDataLen – o tamanho em bytes ocupado pelo campo;
· pBuffer – o valor do campo.
Na Tabela 4 são apresentadas as principais funções da interface IDatabase.
Tabela 4. Funções da interface IDatabase
|
Protótipo |
Parâmetros |
Retorno |
|
IDBRecord * IDATABASE_CreateRecord ( IDatabase * pIDatabase, AEEDBField * pDBFields, int iNumfields ) |
· pIDatabase - ponteiro para objeto IDatabase · pDBFields – ponteiro para os campos a serem inseridos no novo registro · iNumFileds – número de campos do novo registro |
Retorna um ponteiro para um novo registro criado no banco com os campos especificados em pDBFields. Retorna NULL em caso de erro. |
|
IDBRecord * IDATABASE_GetNextRecord (IDatabase * pIDatabase) |
· pIDatabase - ponteiro para objeto IDatabase
|
Retorna uma referência para o próximo registro do banco. |
|
IDBRecord * IDATABASE_GetRecordByID ( IDatabase * pIDatabase, uint16 u16RecID ) |
· pIDatabase - ponteiro para objeto IDatabase · u16RecID – ID do registro
|
Retorna uma referência para o registro identificado por u16RecID. Em caso de pesquisa mal sucedida, retorna NULL. |
|
uint32 IDATABASE_GetRecordCount (IDatabase * pIDatabase)
|
· pIDatabase - ponteiro para objeto IDatabase
|
Retorna a quantidade de registros contidos no banco. Retorna zero se o ponteiro pIDatabase tiver valor inválido. |
|
uint32 IDATABASE_Release (IDatabase * pIDatabase)
|
· pIDatabase - ponteiro para objeto IDatabase |
Fecha o banco e libera ponteiro IDatabase. Retorna zero se o ponteiro já foi liberado. |
|
void IDATABASE_Reset (IDatabase * pIDatabase)
|
· pIDatabase - ponteiro para objeto IDatabase |
Sem retorno. Após a chamada deste método, a chamada a IDATABASE_GetNextRecord() retorna o primeiro registro. |
A API de IDatabase permite a navegação entre registros de uma tabela, com funções que retornam ponteiros para IDBRecord. A partir deste momento, a API de IDBRecord deve ser usada para navegar entre os campos, ou atualizar o conteúdo de um registro. Todos os ponteiros para IDBRecord obtidos, porém, devem ser sempre liberados com IDBRECORD_Release(), caso contrário não será possível fechar a tabela corretamente. Na Tabela 5, você encontra as principais funções da interface IDBrecord.
Tabela 5. Funções da interface IDBRecord
|
Protótipo |
Parâmetros |
Retorno |
|
byte * IDBRECORD_GetField ( IDBRecord * pIDBRecord, AEEDBFieldName * pName, AEEDBFieldType * pDBFieldType, uint16 * pnLen )
|
· pIDBRecord - ponteiro para objeto IDBRecord · pName – ponteiro que armazenará a descrição do campo após a chamada da função · pDBFieldType – ponteiro que armazenará o tipo do campo após a chamada da função · pnLen – ponteiro que armazenará o tamanho do campo após a chamada da função |
Retorna o conteúdo do campo em um formato de array de bytes. Retorna NULL em caso de erro. |
|
boolean IDBRECORD_GetFieldDWord ( IDBRecord * pIDBRecord, dword * pdwRet ) |
· pIDBRecord - ponteiro para objeto IDBRecord · pdwRet – ponteiro para o conteúdo do campo do tipo DWord retornado por esta função. |
Retorna TRUE se o campo for do tipo AEE_FT_DWORD. Caso contrário, retorna FALSE.
|
|
AECHAR * IDBRECORD_GetFieldString(IDBRecord * pIDBRecord) |
· pIDBRecord - ponteiro para objeto IDBRecord
|
Retorna o ponteiro para o conteúdo do registro do tipo AECHAR*. Retorna NULL em caso de erro. |
|
boolean IDBRECORD_GetFieldWord (IDBRecord * pIDBRecord, word * pwRet)
|
· pIDBRecord - ponteiro para objeto IDBRecord · pwRet – ponteiro para o conteúdo do campo do tipo Word retornado por esta função. |
Retorna TRUE se o campo for do tipo AEE_FT_WORD. Caso contrário, retorna FALSE.
|
|
uint16 IDBRECORD_GetID (IDBRecord * pIDBRecord)
|
· pIDBRecord - ponteiro para objeto IDBRecord
|
Retorna o ID do registro. Retorna AEE_DB_ENULLREC Em caso de erro. |
|
AEEDBFieldType IDBRECORD_NextField ( IDBRecord * pIDBRecord, AEEDBFieldName * pName, int16 * pnLen )
|
· pIDBRecord - ponteiro para objeto IDBRecord. · pName – ponteiro que armazenará a descrição do campo após a chamada da função · pnLen – ponteiro que armazenará o tamanho do campo após a chamada da função |
Registro aponta pra o próximo campo. Retorna o tipo do campo encontrado. Utilizado para navegação entre os campos de um registro. Retorna AEEDB_FT_NONE em caso de erro ou de ter alcançado o fim do registro. |
|
uint32 IDBRECORD_Release (IDBRecord * pIDBRecord) |
· pIDBRecord - ponteiro para objeto IDBRecord |
Libera ponteiro IDBRecord. |
|
int IDBRECORD_Remove (IDBRecord * pIDBRecord)
|
· pIDBRecord - ponteiro para objeto IDBRecord. |
Esta função remove o registro do banco e libera o ponteiro de IDBRecord. Retorna SUCCESS em caso de sucesso, ou AEE_DB_EBADREC caso o registro se encontre em um estado ilegal ou AEE_DB_EBADSTATE caso o banco se encontre em um estado ilegal. |
|
void IDBRECORD_Reset (IDBRecord * pIDBRecord)
|
· pIDBRecord - ponteiro para objeto IDBRecord. |
Sem retorno. Após a chamada deste método, a chamada a IDBRECORD_NextField() retorna o primeiro campo. |
|
int IDBRECORD_Update ( IDBRecord * pIDBRecord, AEEDBField * pDBFields, int iNumFields )
|
· pIDBRecord - ponteiro para objeto IDBRecord. · pDBFields – ponteiro para os campos a serem atualizados no registro · iNumFileds – número de campos do registro |
Atualiza o registro com um novo conjunto de campos. Retorna SUCCESS em caso de sucesso; ENOMEMORY em caso de falta de memória; AEE_DB_ENULLFIELD caso pDBFields seja NULL; AEE_DB_EBADFIELDNUM caso iNumFileds seja menor que zero. |
Em geral, os passos seguidos para usar a API de registros são:
1. Criação da instância de IDBMgr através de ISHELL_CreateInstance();
2. Criação ou abertura de uma tabela IDatabase através de IDBMGR_OpenDatabase();
3. Navegação entre registros:
a. Obter instância de IDBRecord através da API de IDatabase;
b. Iteração entre os campos do registro obtido;
c. Ler ou alterar dados;
d. Liberar instância de IDBRecord após uso com IDBRECORD_Release();
4. Liberação da instância de IDatabase através de IDATABASE_Release();
5. Liberação da instância de IDBMgr através de IDBMRG_Release().