Pesquisar

quarta-feira, 16 de dezembro de 2020

Os Segredos de TStringList - Parte 2

Boa noite meus amigos.

Vamos hoje explorar mais alguns recursos desse objeto, o TStringList.

Como eu havia dito no post Parte 1, o StringList é uma das classes mais versáteis do Delphi, vamos agora conhecer alguns de seus recursos.

LoadFromFile e SaveToFile

Quantas vezes ja necessitamos realizar a leitura de um arquivo qualquer no disco, para verificarmos seu conteúdo ou algo do gênero?
O StringList vem em nosso socorro com um método extremamente fácil de usar. LoadFromFile e SaveToFile.

O quão fácil é utilizar este recurso?

procedure TForm2.btn2Click(Sender: TObject);
var
  lStringList: TStringList;
begin
  lStringList:= TStringList.Create;

  lStringList.LoadFromFile('C:\Temp.txt');

end;

Sim, fácil assim, depois dessa linha, o objeto lStringList ja terá todo o conteúdo do arquivo texto contido em "C:\Temp.txt", e pode ser manipulado como quiser através da propriedade Text do componente.

O mesmo vale para a escrita do conteúdo da StringList para o arquivo.

  lStringList.SaveToFile('C:\Temp.txt');

Mais fácil realmente impossível, apenas com esses 2 métodos ja é possível criar um pequeno bloco de notas.
Lembrando ainda que o componente TMemo ja vem com um descendente deste objeto embutido disfarçado com o nome de "Lines". Então, para popularmos um TMemo com o conteúdo de um arquivo basta simplesmente utilizarmos a propriedade "Lines" do TMemo do seguinte modo:

  Memo1.Lines.LoadFromFile('C:\Temp.txt');

E para salvar o conteúdo:

  Memo1.Lines.SaveToFile('C:\Temp.txt');

Desse modo, com apenas 2 componentes temos um bloco de notas bem rudimentar mas utilizável.

Claro que tanto os métodos LoadFromFile quanto o SaveToFile, são recomendados para arquivos com até o máximo de 10mb de tamanho (claro que depende do PC), caso o contrário essa pode ser uma operação bem demorada. Para arquivos maiores, recomenda-se utilizar as funções de manipulação de arquivos do próprio Delphi (AssignFile, CloseFile, etc...).

Split String

Agora vamos supor que você queira montar uma lista de palavras separadas por vírgula, que não se sabe a quantidade. Como por exemplo uma lista de fields de um dataset para a montagem de um SELEC.

Provavelmente teríamos um código parecido com este:

var
  Count: integer;
  lListaDeCampos: string;
begin

  for Count := 0 to Pred(dsCliente.Fields.Count) do
  lListaDeCampos:= lListaDeCampos + DataSetCliente.Fields[Count].FieldName + ',';

  //Remover último caractere
  lListaDeCampos:= Copy(lListaDeCampos,1,length(lListaDeCampos)-2);
  ShowMessage(lListaDeCampos)
end;

Isso funciona muito bem, porem o StringList possui uma solução bem mais elegante:

var
  Count: integer;
  lListaDeCampos: TStringList;
begin
  lListaDeCampos:= TStringList.create;

  for Count := 0 to Pred(dsCliente.Fields.Count) do
    lListaDeCampos.Add(DataSetCliente.Fields[Count].FieldName);

  ShowMessage(lListaDeCampos.DelimitedText);
end;

Como podem ver, com a utilização da classe TStringList, o código fica bem mais elegante e muito mais legível.

Leituras de Chave - Valor (Semelhante a arquivos INI)

Embora o Delphi possua um excelente mecanismo de leitura e escrita de arquivos INI (classe TIniFile), ainda podemos utilizar o TStringList para realizarmos essa tarefa de forma básica.

Vamos supor que exista um arquivo INI com o seguinte conteúdo:

[EMPLOYEE]
DriverID=IB
Protocol=TCPIP
Database=localhost:C:\examples\database\employee.gdb
User_Name=sysdba
Password=masterkey
CharacterSet=UTF-8
ExtendedMetadata=True


Utilizando o TStringList, após fazermos a carga do arquivo com "LoadFromFile" é muito fácil obtermos qualquer valor utilizando a propriedade "Values" do objeto, onde simplesmente passamos a chave para obtermos o valor.

Ex:

ShowMessage(lStringList.Values['DriverID']); //Retorna "IB"
ShowMessage(lStringList.Values['Protocol']); //Retorna "TCPIP"
ShowMessage(lStringList.Values['User_Name']); //Retorna "sysdba"
... Tenho certeza que ja entenderam... :)

Realmente muito simples não é, podemos inclusive adicionar ou substituir valores ao arquivo:

//Adicionando a chave "Transaction" com o valor "S"
lStringList.Values['Transaction']:= 'S';

O trecho acima é o mesmo que:

lStringList.Add('Transaction=S');

Claro que neste último caso a chave valor será adicionada ao final do arquivo, sem realizarmos a verificação se ela ja existe ou não.
Obviamente, após adicionarmos a chave com qualquer um desses métodos, o arquivo deve ser salvo com o método "SaveToFile" para ser persistido no disco.

Ainda é necessário mencionar que este modo de leitura não considera repetições de chaves, trazendo sempre a primeira ocorrência da chave na lista e ignorando as repetições.
Também vale lembrar que não é possível setorizar as informações, pois o TStringList não possui um mecanismo de busca setorizada (utilização de "SECTIONS" no arquivo, para isto utilize a classe específica de leitura de arquivos INI, a TIniFile).

NOTA SOBRE ESTE TIPO DE UTILIZAÇÃO: Por debaixo dos panos, o TStringList executa a pesquisa de chave percorrendo todos os itens, procurando o separador dentro de cada item e comparando a parte do nome com a chave fornecida. Não é preciso dizer que ele causa um grande impacto no desempenho, então esse mecanismo só deve ser usado em lugares não críticos e raramente repetidos(como na carga do sistema, onde o procedimento sera realizado apenas uma vez durante todo o ciclo de execução da aplicação). Nos casos em que o desempenho é importante, deve-se usar TDictionary <TKey, TValue> de System.Generics.Collections que implementa a pesquisa binária.


Conclusão

Claro que todos estes exemplos são meramente ilustrativo, pois não realizamos a liberação do objeto na memória utilizando o método correto (.free).
Pelo que vimos não nos resta dúvidas sobre a utilização desta classe muito versátil do TStringList.

Obrigado a todos pela atenção e espero ter ajudado.
Grande abraço!!

Nenhum comentário:

Postar um comentário