segunda-feira, novembro 20, 2006

Curso de wxWidgets, post 10: Mais sobre arquivos com wxTextFile

Agora será apresentada a classe wxTextFile. Essa classe permite manipular arquivos de texto e possui alguns métodos bastante úteis. Como eu havia comentado no post 8, eu senti falta de alguns métodos interessantes em wxFile, como por exemplo, ler uma linha inteira de um arquivo. Só depois que eu descobri a wxTextFile :P

A abertura de um arquivo para leitura se dá com o método wxTextFile::Open():

wxTextFile File;
File.Open("arquivo.txt");


Caso o arquivo não possa ser aberto ou não exista, wxTextFile::Open() retornará falso.

Agora, basta caminharmos pelas linhas e ler o conteúdo do arquivo. Podemos saber o número de linhas em um arquivo com wxTextFile::GetLineCount() (retornando o número de linhas) e ler cada linha com wxTextFile::GetLine() (retornando um objeto wxString com o conteúdo da linha lida). Veja um exemplo de leitura linha a linha:

for (unsigned int line = 0; line < File.GetLineCount(); line++)
txt_file->AppendText(File.GetLine(line) + wxT("\n"));


O laço acima percorre cada linha do arquivo e adiciona em um objeto do tipo wxTextCtrl.

Após ter lido todo o arquivo, podemos fechá-lo com wxTextFile::Close():

File.Close();


Já no caso de gravações, temos que criar o arquivo com wxTextFile::Create():

wxTextFile File;
File.Create("arquivo.txt");


Caso o arquivo não possa ser criado, wxTextFile::Create() retornará falso.

Agora, basta chamar wxTextFile::AddLine() para adicionar linhas no arquivo:

File.AddLine(wxT("Linha 1"));
File.AddLine(wxT("Linha 2"));
File.AddLine(wxT("Linha 3"));


Por último, devemos gravar as alterações no disco e fechar o arquivo:

File.Write();
File.Close();


Existem também outros métodos interessantes:

wxTextFile::GoToLine(size_t n) leva você até a linha n.

wxTextFile::GetFirstLine(), GetNextLine(), GetPrevLine(), GetLastLine() retornam a primeira linha, a próxima, a anterior e a última respectivamente.

Você também pode inserir uma linha em um local específico com wxTextFile::InsertLine() e pode remover qualquer linha com wxTextFile::RemoveLine().

O exemplo de editor de textos

Modifiquei o programa do post 9 para usar wxTextFile no lugar de wxFile. Vejam o programa alterado abaixo:

/* A Casa de Just - http://jpjust.blogspot.com
* Curso de wxWidgets: Exemplo de um editor de textos usando wxTextFile
*
* O objetivo deste código é demonstrar o uso da classe wxTextFile
* para efetuar leitura e escrita em um arquivo de texto, além
* de mostrar o uso básico das classes wxApp, wxFrame, wxStaticText,
* wxButton, wxTextCtrl e wxBoxSizer, assim como o tratamento de
* eventos e as funções wxFileSelector() e wxMessageBox()
* (tópicos abordados do post 2 ao post 8 do curso).
*
* wxTextCtrl possui dois métodos para carregar e salvar um arquivo
* (wxTextCtrl::LoadFile() e wxTextCtrl::SaveFile()), porém, wxTextFile
* é utilizado para demonstrar seu uso. No trecho onde a leitura e
* escrita são feitas, existem comentários explicando como utilizar
* estes métodos.
*
* Copyright (c) João Paulo Just <jpjust@justsoft.com.br>
* A Casa de Just - http://jpjust.blogspot.com
* 20 de novembro de 2006, 20:25, Ilhéus, BA, Brasil.
*/

#include <wx/wx.h>
#include <wx/textfile.h>

// IDs
enum
{
ID_BTNLOAD,
ID_BTNSAVE
};

// Classe do programa
class MeuPrograma: public wxApp
{
public:
// Método principal
virtual bool OnInit(void);
};

// Classe do frame
class MeuFrame: public wxFrame
{
public:
// Construtor
MeuFrame(void);

// Eventos
void OnLoadClick(wxCommandEvent &event);
void OnSaveClick(wxCommandEvent &event);

DECLARE_EVENT_TABLE()

private:
// Widgets do frame
wxButton *btn_load;
wxButton *btn_save;

wxStaticText *lb_filename;

wxTextCtrl *txt_file;
};

// Inicialização do programa
bool MeuPrograma::OnInit(void)
{
MeuFrame *frame = new MeuFrame();
frame->Show();
SetTopWindow(frame);
return true;
}

// Tabela de eventos
BEGIN_EVENT_TABLE(MeuFrame, wxFrame)
EVT_BUTTON(ID_BTNLOAD, MeuFrame::OnLoadClick)
EVT_BUTTON(ID_BTNSAVE, MeuFrame::OnSaveClick)
END_EVENT_TABLE()

// Construtor do frame
MeuFrame::MeuFrame(void)
:wxFrame(NULL, wxID_ANY, wxT("Arquivos"))
{
// Sizer e widgets
wxBoxSizer *sizer_h = new wxBoxSizer(wxHORIZONTAL);
wxBoxSizer *sizer_v = new wxBoxSizer(wxVERTICAL);

btn_load = new wxButton(this, ID_BTNLOAD, wxT("Abrir"));
btn_save = new wxButton(this, ID_BTNSAVE, wxT("Salvar"));

lb_filename = new wxStaticText(this, wxID_ANY,
wxT("Sem titulo.txt"));

txt_file = new wxTextCtrl(this, wxID_ANY, wxEmptyString,
wxDefaultPosition, wxDefaultSize, wxTE_MULTILINE);

// Posicionamento
sizer_h->Add(btn_load, 0, wxALL, 5);
sizer_h->Add(btn_save, 0, wxALL, 5);
sizer_h->Add(lb_filename, 1, wxALL, 5);

sizer_v->Add(sizer_h, 0, wxALL, 0);
sizer_v->Add(txt_file, 1, wxALL | wxEXPAND, 5);

SetSizerAndFit(sizer_v);

// Boas-vindas
wxMessageBox(wxT("Seja bem-vindo(a) a mais um maravilhoso programa! :)"),
wxT("Bem-vindo(a)!"), wxICON_INFORMATION);
}

// Botão de leitura
void MeuFrame::OnLoadClick(wxCommandEvent &event)
{
wxString Filename;

// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxOPEN | wxFILE_MUST_EXIST);

// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;

// Tenta abrir o arquivo com wxTextFile
wxTextFile File;
if (File.Open(Filename) == false)
return;

// Lê o conteúdo do arquivo linha a linha
for (unsigned int line = 0; line < File.GetLineCount(); line++)
txt_file->AppendText(File.GetLine(line) + wxT("\n"));

// Não é preciso todo este código para ler um arquivo
// e exibí-lo em um wxTextCtrl. O trecho acima foi
// escrito apenas para que você entenda a classe wxTextFile.
// wxTextCtrl possui um método próprio para ler o
// conteúdo de um arquivo. Tente comentar o trecho acima
// e usar o método abaixo para fazer a leitura:

//txt_file->LoadFile(Filename);

// Fecha o arquivo
File.Close();

// Atualiza o nome
lb_filename->SetLabel(Filename);
}

// Botão de salvamento
void MeuFrame::OnSaveClick(wxCommandEvent &event)
{
wxString Filename;

// Abre diálogo de arquivo
Filename = wxFileSelector(wxT("Selecione o arquivo"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxT("*.txt"), wxSAVE | wxOVERWRITE_PROMPT);

// Se arquivo inválido, sai do método
if (Filename == wxEmptyString)
return;

// Tenta criar o arquivo com wxTextFile
wxTextFile File;
if (File.Create(Filename) == false)
return;

// Limpa o arquivo, caso exista conteúdo nele
File.Clear();

// Percorre a caixa de texto gravando o conteúdo
// no arquivo aberto, linha a linha
for (unsigned int line = 0; line < txt_file->GetNumberOfLines(); line++)
File.AddLine(txt_file->GetLineText(line));

// Neste ponto, eu também poderia usar um método
// de wxTextCtrl para salvar o arquivo. Tente
// comentar o trecho de gravação acima e descomente
// a linha abaixo para testar:

//txt_file->SaveFile(Filename);

// Salva o arquivo em disco e fecha
File.Write();
File.Close();

// Atualiza o nome do arquivo
lb_filename->SetLabel(Filename);
}

IMPLEMENT_APP(MeuPrograma)

Um comentário:

Anônimo disse...

Caro Just, estava vendo o seu tutorial de como utilizar a wxTextFile e tentando aplicá-la a um programa que estou construindo.

Gostaria de saber como fazer para a wxTextFile ler um arquivo em txt e imprimir cada linha em um wxTextCtrl diferente.

Por favor me ajude.

Envie a resposta para a o meu e-mail por gentileza: xxdaniel.ls@gmail.com

Desde já agradeço a sua ajuda e compreensão.

Daniel Lucena