terça-feira, novembro 07, 2006

Curso de wxWidgets, post 8: Manipulando arquivos

Manipular arquivos em C não é complicado, mas de qualquer forma, irei apresenter uma classe do wxWidgets que o ajuda nesta tarefa, a wxFile.

wxFile é simples de usar. Seu construtor:

wxFile(const char* filename, wxFile::OpenMode mode = wxFile::read)

filename: O caminho do arquivo a ser aberto.

mode: Modo de acesso. Pode ser wxFile::read, wxFile::write ou wxFile::read_write.


Para abrir um arquivo para leitura, basta especificar o caminho do arquivo e usar o modo wxFile::read:

wxFile arquivo("c:\\arquivo.txt", wxFile::read);


Leitura e escrita? Use wxFile::read_write:

wxFile arquivo("c:\arquivo.txt", wxFile::read_write);


Após aberto, já podemos manipular o arquivo. A leitura é feita com o método wxFile::Read():

char linha[256];
int lido, max = 255;

wxFile arquivo("c:\\arquivo.txt", wxFile::read);
lido = arquivo.Read(linha, max);


lido irá conter a quantidade de bytes lidos pelo método. linha irá guardar o conteúdo lido e max indica o máximo de bytes a ser lido (neste caso, usado para delimitar a quantidade de dados que será guardado em linha). No caso de leitura de arquivos de texto, a quantidade de bytes a serem lidos deve ser o tamanho do buffer menos 1, para deixar espaço para o \0 de final de string em C.

Para gravar, simplesmente use o método wxFile::Write()

wxString Linha = wxT("Nova linha de texto!");
bool gravado;

wxFile arquivo("c:\\arquivo.txt", wxFile::read);
gravado = arquivo.Write(Linha);


Este método usa como argumento um wxString. Existe um segundo argumento, usado para fazer conversão do tipo da string. A conversão é utilizada caso você esteja usando wxWidgets em uma compilação (UNICODE, por exemplo) e deseja gravar o arquivo em outro formato (no caso, ANSI).

Se você prefere gravar no formato cru, como no C puro, existe também o método wxFile::Write(const void* buffer, wxFileOffset count) que funciona de forma semelhante ao wxFile::Read(). Ele recebe como argumento uma variável qualquer com algum conteúdo e um valor indicando a quantidade de bytes a serem gravados.

É preciso saber que essas operações serão feitas no início do arquivo. Ou seja, se você pede para ler 10 bytes, a classe wxFile irá ler os primeiros 10 bytes do arquivo. Se logo em seguida você solicitar uma escrita, seu buffer será gravado a partir do 11º byte. Para fazer leituras e escritas em outras partes do arquivo, use wxFile::Seek():

wxFileOffset Seek(wxFileOffset ofs, wxSeekMode mode = wxFromStart)

ofs: Offset a percorrer.

mode: Origem da busca. Pode ser wxFromStart, wxFromEnd ou wxFromCurrent.


Se você quiser fazer uma leitura a partir do 20º byte, por exemplo, basta usar o método wxFile::Seek() antes do wxFile::Read():

arquivo.Seek(20, wxFromStart);
arquivo.Read(buffer, 100);


O exemplo acima lê 100 bytes a partir do 20°, guardando o conteúdo em buffer. O mesmo vale para escritas, basta usar wxFile::Seek() antes de wxFile::Write().

Caso queira gravar no final do arquivo, use wxFile::SeekEnd():

arquivo.SeekEnd();
arquivo.Write(Linha);


Após ter feito todas as leituras e escritas desejadas, feche o arquivo com wxFile::Close().

Outros métodos interessantes

Além de leitura e escrita, podemos fazer outras coisas com wxFile. Por exemplo, obter o tamanho do arquivo aberto com wxFile::Length():

int tamanho = arquivo.Length();


Ou até verificar se o arquivo existe com wxFile::Exists():

bool existe = wxFile::Exists("c:\\arquivo.txt");


Finalizando

Na minha opinião pessoal, não há uma vantagem grandiosa em usar wxFile. Quero dizer, usar wxFile não nos dá tanta vantagem para tratar arquivos quanto wxString nos dá para tratar strings. Eu senti falta de um método que lesse n bytes, gravando-os em um wxString ou algum método que pudesse ler toda uma linha de uma vez.

Olhei o manual da próxima versão (2.7.2, futuramente 2.8.0) e não vi nada deste tipo em wxFile. Acabei ficando com vontade de implementar isso. :)

Nenhum comentário: