[Delphi] Trabalhando com arquivos INI

[Delphi] Trabalhando com arquivos INIPra estrear a página sobre programação, neste breve tutorial abordarei os conceitos e os passos necessários para trabalhar com arquivos INI pelo Delphi. Em uma breve explicação, a principal função de um arquivo INI é armazenar dados básicos de configuração da aplicação por meio de seções e valores, muito utilizado por desenvolvedores atualmente.

 

Por quê utilizar arquivos INI?
Vamos supor que temos um sistema para emissão de pedidos, e uma das funções deste sistema é gravar os arquivos PDF dos pedidos emitidos em uma pasta no computador, para que depois o usuário possa enviá-los aos seus clientes. No código-fonte do sistema, definimos a pasta de armazenamento dos arquivos PDF como “C:\Aplicativo\PDF”, conforme solicitado pelo usuário. Porém, alguns meses depois, o usuário decide comprar um disco externo para armazenar estes arquivos PDF. Mas espere aí, o nosso sistema somente aceita gravar os arquivos no diretório “C:\Aplicativo\PDF”, não é? Portanto, a única solução é abrir o código-fonte, alterar a pasta de armazenamento, compilar o software e atualizá-lo no computador do usuário. Ok, é uma solução, mas e se futuramente ele decidir alterar a pasta de armazenamento novamente?

Este é um tipo de situação comum no cenário de desenvolvimento de software. No exemplo acima, é possível contornar este problema utilizando um arquivo do tipo INI para armazenar o diretório da gravação dos pedidos. Dessa forma, essa e outras configurações do software são armazenadas externamente, e podem ser editadas sem a necessidade de manutenção no sistema, e melhor, dispensando a gravação de parâmetros no banco de dados.


Como se define um arquivo INI?

Por armazenar um conteúdo de configuração, o arquivo INI possui uma estrutura padrão constituída de seções, propriedades e valores.

  • As seções representam agrupamentos de valores, ou seja, o assunto no qual se destina os valores armazenados.
  • As propriedades são os nomes das configurações que deseja-se armazenar.
  • Os valores, como o próprio nome diz, armazenam os dados das configurações.

Para esclarecer melhor, a estrutura do arquivo INI é exemplificada no código abaixo:

[Seção 1]
Propriedade1=Valor1
Propriedade2=Valor2
Propriedade3=Valor3
 
[Seção 2]
Propriedade1=Valor1
.
.
.

Utilizando a situação acima como exemplo, poderíamos definir o arquivo INI da seguinte forma:

[Configuracao]
DiretorioPDF=C:\Aplicativo\PDF

Observe que forneci um nome sugestivo para a seção e para a propriedade, para que depois fique mais fácil para acessá-las pelo Delphi.


Lendo e gravando arquivos INI pelo Delphi
Agora que conhecemos o que é um arquivo INI, sua função e estrutura, basta escrevermos os métodos necessários para ler e gravar dados pelo Delphi. O primeiro passo é declarar a referência IniFiles na cláusula uses da unit, conforme o código abaixo. Este passo é necessário para que o Delphi reconheça os métodos que usaremos para manipular o arquivo INI.

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics,
  Controls, Forms, Dialogs, IniFiles;

Insira um componente TEdit no formulário, nomeando-o como “edtMensagem”. Em seguida, adicione também um botão e altere a propriedade Caption para “Gravar Arquivo INI”. A função deste botão será gravar a mensagem contida na TEdit dentro do arquivo INI que será criado. O próximo passo é criar uma variável do tipo TIniFile, e então instanciá-la com o caminho e nome do arquivo INI. Para efeitos de demonstração, criaremos o arquivo INI dentro do “C:\”, mas esta não é uma regra. O arquivo pode ser armazenado em qualquer diretório no computador.

Mãos à obra: dê dois cliques no botão e insira o seguinte código:

var
  ArquivoINI: TIniFile;
begin
  ArquivoINI := TIniFile.Create('C:\Configuracao.ini');
  ArquivoINI.WriteString('Exemplo', 'Mensagem', edtMensagem.Text);
  ArquivoINI.Free;
  ShowMessage('Mensagem armazenada com sucesso!');
end;

No exemplo acima, após a variável ter sido declarada e instanciada, já podemos manipular o conteúdo do arquivo INI. Para gravar o conteúdo, utilizei o método WriteString, responsável por armazenar o dado na seção e propriedade informados. O método WriteString exige 3 parâmetros de entrada: o primeiro é nome da seção, o segundo é o nome da propriedade, e o terceiro, o valor a ser armazenado. Veja que forneci o nome Exemplo para a seção e o nome Mensagem para a propriedade. Estes nomes serão importantes posteriormente na leitura do arquivo.

Por fim, utilizamos o método Free para liberar a referência do arquivo da memória, já que terminamos de manipulá-lo. Execute a aplicação, clique no botão e depois verifique que o arquivo “Configuracao.ini” foi criado no “C:\” do computador. Se você abrir este arquivo, verá que ele estará na seguinte estrutura:

[Exemplo]
Mensagem=Mensagem da TEdit

Pronto, gravamos a informação no arquivo INI!
Porém, de nada adianta gravar uma informação se não sabemos como acessá-la, não é? Bem, volte à aplicação e adicione um novo botão, alterando a propriedade Caption apara “Ler Arquivo INI”. O código deste botão é bem semelhante ao código acima, exceto pelo método de acesso ao conteúdo:

var
  ArquivoINI: TIniFile;
  Mensagem : string;
begin
  ArquivoINI := TIniFile.Create('C:\Configuracao.ini');
  Mensagem := ArquivoINI.ReadString('Exemplo', 'Mensagem', 'Erro ao ler o valor');
  ArquivoINI.Free;
  ShowMessage('Mensagem armazenada no arquivo INI: ' + #13 + Mensagem);
end;

O método ReadString tem a função de ler o dado da seção e propriedade informados por meio de três parâmetros de entrada: o primeiro é o nome da seção, o segundo é nome da propriedade, e o terceiro é o valor retornado caso ocorra algum erro na leitura da propriedade. Nesta rotina, a mensagem contida no arquivo INI foi atribuída a uma variável do tipo string, e em seguida exibida ao usuário através do ShowMessage.


E se eu precisar gravar outros valores?
É importante ressaltar que para o exemplo acima utilizei somente os métodos para gravação e leitura de valores do tipo string. Para manipular outros tipos de dados, basta utilizar as respectivas funções disponibilizadas pelo Delphi, como WriteInteger e ReadInteger para número inteiro, WriteFloat e ReadFloat para números reais ou WriteDate e ReadDate para datas. Nada impede também que vários dados sejam gravados ou lidos em uma única rotina, como o exemplo abaixo:

// Gravação
ArquivoINI := TIniFile.Create('C:\Configuracao.ini');
ArquivoINI.WriteString('Valores', 'Mensagem', 'Este é um exemplo');
ArquivoINI.WriteInteger('Valores', 'Contador', 5);
ArquivoINI.WriteFloat('Valores', 'Preço', 12.56);
ArquivoINI.WriteDate('Valores', 'Backup', '20/08/2012');
 
// Leitura
Edit.Text := ArquivoINI.ReadString('Informacoes', 'Usuario', '');
RadioGroup.ItemIndex := ArquivoINI.ReadInteger('Informacoes', 'Opcao', 0);
 
// Liberação da memória
ArquivoINI.Free;

Simples, não? Utilizar arquivos INI certamente garante uma maior flexibilidade nas configurações da aplicação, portanto, procure utilizá-los sempre quando possível. O projeto de exemplo foi desenvolvido em Delphi XE e pode ser baixado neste link.

Ops, ocorreu algum erro ao manipular o arquivo INI?
Veja se uma das respostas abaixo pode lhe ajudar:

1) Ao compilar o projeto, recebo a mensagem: E2003 Undeclared identifier: ‘TIniFile’.
Declare a referência IniFiles na seção uses do formulário, logo no início do arquivo de código-fonte.

2) Ao compilar o projeto, recebo a mensagem: E2035 Not enough actual parameters.
Um dos métodos não está recebendo a quantidade de parâmetros necessária. O método WriteString, por exemplo, exige três parâmetros de entrada que devem ser obrigatoriamente informados. Se houver dúvidas na quantidade de parâmetros exigida, pressione Ctrl + Shift + C para exibir a lista de parâmetros da função.

3) Declarei e instanciei a variável, mas o arquivo não é criado.
Verifique se a pasta informada no código-fonte realmente existe no computador, e se os nomes estão corretos. Além disso, existem algumas pastas que são protegidas pelo sistema. Se o usuário não possuir permissão de acesso à pasta, o arquivo não será criado por questões de segurança.

4) Recebo uma exceção de Access Violation ao ler ou gravar o arquivo.
Verifique se ele está sendo criado corretamente através do método Create. Se você tentar ler ou gravar dados antes de criar o arquivo, o Delphi retornará um erro de acesso. Lembre-se também de liberar a variável da memória após terminar de trabalhar com o arquivo INI.

5) Os valores são gravados, mas não são lidos corretamente.
Este problema exige atenção nos parâmetros dos métodos. Confira se o nome do arquivo gravado é o mesmo nome que está sendo utilizado na rotina de leitura. E o mais importante: confira os nomes das seções e propriedades. Se o Delphi não encontrar a seção ou propriedade informada, o retorno será nulo. Procure também utilizar os métodos para o mesmo tipo de dado armazenado, ou seja, se gravar um valor com o método WriteString, leia-o com ReadString, e assim por diante.

 

Em caso de dúvidas, erros ou sugestões, deixe um comentário!
Um abraço a todos!


 

Compartilhe!
Share on FacebookTweet about this on TwitterShare on LinkedInShare on Google+Pin on PinterestEmail this to someone

46 comentários

  1. Quero parabenizá-lo pelos ótimos artigos que você tem publicado, pois, percebo que o seu diferencial em relação aos outros sites que postam artigos sobre Delphi esta na didática com detalhes. continue assim, sempre detalhista, ajudando os programadores iniciantes a conhecer e a pegar o gosto pela Ferramenta Delphi.

  2. André você esta de parabens, o post tem uma didática maravilhosa rica em detalhes e de facio compressão.
    Parabens novamente pelo otimo trabalho.

  3. Otima explicação, parabéns.
    Já utilizo esses tipo de arquivo há algum tempo, mas estou tendo problemas para criptografa-lo para que o usuário quando abrir não possa visualiza-lo e modifica-lo.
    Poderia sugerir uma rotina de criptografia do arquivo ini para ler e cria-lo.
    obrigado

    1. Olá, Hideki. Infelizmente não há uma forma consistente de criptografar arquivos INI, ainda mais que, caso fosse possível, você teria alguns problemas de ler as seções e as chaves do arquivo no Delphi. Uma alternativa é usar uma função de criptografia para gravar os valores no arquivo INI, como por exemplo, ao invés de gravar “Delphi”, a função gravaria “5&R0@”.

  4. Olá!
    Como eu faria para poder ler um arquivo ini em linhas… no caso preciso colocar nomes de schemas do banco de dados, um em cada linha de um memo, gravo estes dados em um .ini criptografado e leio em runtime para setar o schema no banco de dados e fazer minhas buscas. Como posso fazer isto? Obrigada!

  5. Olá, como fária pra que o arquivo ini se relacionasse com o banco de dados do meu interbase, no caso as relações já estão tudo feitas(cadastrar,apagar,atualizar)? Preciso fazer isso, pro meu software funcionar em outro computadores além do meu. Se souber me ajudar agradeceria, abraço.

  6. Olá, novamente. Ajudou assim, mas continuo com uma dúvida, eu uso o Ibconsole, e para usar o banco que ele cria eu tenho de usar um usuario e um password, que são SYSDBA e masterkey respectivamente (não estou em casa, e aqui não posso testar, por isso a pergunta). Esses dois seriam a secao e a chavebancodedados ou não? Desculpa se for alguma pergunta idiota, mas sou um pouco novo no Delphi, sei umas coisas mas esse não, e gosto de aprender para eu conseguir desenvolver futuros projetos com um bom funcionamento, desculpa o incomodo, abraço e obrigado.

    1. Olá, Ricardo. Imagina rapaz, não existem perguntas idiotas. Todo mundo está aprendendo no dia-a-dia!
      Ricardo, no código que lhe enviei há uma seção e uma chave somente para efeito de exemplo. Você pode gravar uma seção com várias chaves para armazenar quantos valores forem necessários:
      [Secao]
      UsuarioBD=SYSDBA
      SenhaBD=masterkey
      CaminhoBD=C:\Aplicativo\Banco.gdb

      Vou lhe enviar um e-mail com mais detalhes.

  7. Olá Andre, estou tentando configurar uma conexão com meu banco de dados utilizando arquivo de extensão .ini, a configuração local funciona perfeitamente porém estou tendo problemas quando tento me conectar em rede a um servidor, ja tentei mapear a unidade e colocar o caminho mapeado e também pelo endereço de ip mas não obtive exito, o que pode ser?

  8. Bom dia, André! Primeiramente, desculpe por ‘desenterrar’ seu post, mas estou com uma dúvida. Como faço para ler mais de um valor na seção? Por exemplo:
    [Seção1]
    propriedade1 = valor1
    propriedade2 = valor2
    propriedade3 = valor3
    Como faço para retornar somente o valor1, valor2 e valor3?
    Obrigado por sua atenção. Abraço!

    1. Olá, Rafael! Não se preocupe em comentar nos artigos antigos. Os comentários são importantes e complementam as informações do artigo.
      Bem, a respeito da sua dúvida, os arquivos INI são gravados em uma estrutura onde cada chave pode ter somente um único valor, portanto, para ler cada valor, é preciso acessar a sua chave correspondente.
      Uma alternativa para este caso é armazenar o valor em apenas uma chave com algum tipo de delimitador, como a vírgula, o pipe ( | ) ou barras. Por exemplo:
      propriedade=valor1|valor2|valor3
      Dessa forma, no Delphi, basta ler estes delimitadores e considerar cada palavra separada como uma linha.

  9. Quero parabenizá-lo pelo ótimo site! Todos os artigos e publicações são claras, objetivas e tem sido de muita ajuda.

  10. Ola amigo Andre Luis, primeiramente muito obrigado pelo otimo tutorial, mas estou com uma duvida..

    eu criei um arquivo config.ini com 2 seções uma [LIGAR] e outra [DESLIGAR] na primeira seçao eu coloquei :

    [LIGAR]
    LOGIN = \\Sem valores estipulado usuario estipula
    LOGIN_Dir= \\Sem local estipulado usuario estipula
    LOGIN_Delay=\\Sem tempo para execução usuario estipula o intervalo de tempo de uma execuçao para outra

    E na segunda seção eu coloquei:

    [DESLIGAR]
    LOGIN = \\ Deixei em branco para que o usuario estipule o executavel que ele quer encerrar, como os valores acima tambem ficaram em branco para que o usuaria possa estipular e a interface leia e abra co arquivo no diretorio que ele esta armazenado, mas nao estou conseguindo criar o codigo em delphi com um botão para fazer esta açao funcionar para ligar e ler todas as informaçoes que o usuario colocou no config.ini e executar o arquivos .exe… por favor poderia me ajudar com isso..
    obrigado.

  11. Caro amigo Andre Luis muito obrigado por me responder por email. seu codigo resolveu meu problema.. obrigado

  12. Amigo no meu caso preciso gravar 3 seção, cada seção vai ser gravado vários valores, no meu caso ele esta gravando, mas toda vez que entro com um dado novo ele sobrescreve o que já existe. eu teria que gravar uns 30 valores em cada seção, para fazer a leitura depois.

    1. Olá, Maycom! Isso mesmo, a cada vez que você escrever um valor em uma chave, o valor antigo será sobrescrito. Se você pretende gravar vários valores em uma única seção, então terá que especificar nomes diferentes para as chaves.

  13. Boa noite meu caro! Suas explicações estão bastante claras, parabéns! Nós curiosos em programação ficamos muito gratos, pois nossos “programinhas de fundo de quintal” precisam funcionar e nós não sabemos como fazer isso, mas existem profissionais competentes como você que não se esquivam de ajudar a nós que apenas brincamos com programação! rsrsrs…

    Eu estou pesquisando sobre INI para um programinha básico que estou fazendo, e já consegui gerar e gravar dados em um INI com sucesso.
    Esses dados, nada mais são do que o caminho de uma (ou talvez outras futuramente)planilha que desejo que seja aberta quando eu clicar no menu de meu pequeno programa onde consta o nome desta planilha.
    Precisei fazer por meio de INI, por que algumas vezes outros usuários ficam movendo ou trocando o nome desta planilha, e eu obviamente acho mais conveniente poder colocar em um INI através da opção configurações de meu programa, o caminho desta planilha do que ficar mexendo no fonte.

    Ok, isso eu já consegui…

    Mas, eu gostaria que quando eu clicasse no menu onde está o nome desta planilha, o programa acessasse este caminho que está gravado no INI, e em seguida abrisse a planilha.

    Achei que daria para fazer por Shell execute ou por Winexec, mas obviamente não funciona, e eu não sei MESMO como fazer, já que tenho menos de um mês de aprendizado em Delphi…

    Será que há como fazer isso??

    1. Olá, Jadilson! Em primeiro lugar, devo parabenizá-lo pela clareza na sua escrita! Você conseguiu se expressar muito bem no comentário e me deixou sem sombra de dúvidas.
      Bom, Jadilson, já que é uma questão mais ampla, vou lhe enviar um e-mail com uma possível solução, ok?
      Abraço!

  14. André, bom dia!

    Achei que seria interessante deixar um comentário
    a respeito de minha pergunta, também aqui no blog, já que agora estou visitando com frequencia.

    Agradeço novamente por sua ajuda!
    Como eu já lhe disse, o código que você me enviou
    é simples para você que tem conhecimento e para mim seria algo bem mais difícil(e olha que procurei pela internet para ver se achava algo que me ajudasse, e se há, não encontrei!)

    Felizmente você não se esquiva de ajudar, Muito obrigado!

    Que Deus o abençoe e à sua família!

    1. Olá, Jadilson! Novamente lhe agradeço pelo apoio e pelo comentário no blog!
      Fiquei contente ao saber que a minha ajuda foi útil para solucionar a sua dúvida. Espero que continue visitando o blog.
      Um grande abraço!

  15. Parabéns pelo artigo. Gosto de programar em delphi pra desestressar e agora entendi como estruturar um arquivo de configuração por meio de um arquivo INI. Já tentei em outras explicações mas a sua é super simples e direta. Valeu cara!

  16. tenho um software que usa um arquivo INI , o qual controla quantidade de terminal para acessar o programa juntamente com a licença, gostaria de saber se tem como editar o arquivo para alterar a quantidade de terminal para acessar o programa e como faço isso ???

    1. Olá, Lucio!
      Arquivos INI podem ser editados pelo bloco de notas, já que são arquivos de texto simples.
      Para isso, clique com o botão direito no arquivo e selecione “Abrir com” > “Bloco de notas”.

      Abraço!

  17. Muito bom seus artigos. São de grande utilidade e de fácil aprendizagem. São artigos de fácil entendimento e que prendem a nossa atenção. Parabéns.

  18. Olá André, primeiramente parabéns pelo ótimo conteúdo disponibilizado.

    Vai minha dúvida: Como ler determinada propriedade quando seus dados possuem quebra de linha, ou seja, ocupa mais de uma linha?

    Explico: Salvar dados contidos em um componente TMemo(com vários “enters”) e depois recuperá-lo novamente nesse TMemo.

    Utilizando o código abaixo, ele só me retorna a primeira linha da propriedade.

    memo.lines.text := ArquivoINI.ReadString(‘Exemplo’, ‘Mensagem’, ”);

    Tem como fazer utilizando o .ini ou há outra opção melhor.(Apesar que todo o aplicativo já está funcional e mudar isso seria trabalhoso demais).

  19. Gostei muito da sua explicação sobre arquivos ini. Só que estou tentando executar programas portáteis por meio de um apricativo que eu criei, gostaria de saber se da para fazer isso por meio de arquivos ini.
    Peço, por favor, que não mande exemplo com imagem pois sou cego. Rsrsr Parabéns pela página . Já adicionei aos meus favoritos

    1. Olá, Edilberto!
      Muito obrigado pelo seu feedback sobre o artigo! Isso é muito importante para que eu continue o meu trabalho!
      Sim, Edilberto, você pode programar os seus aplicativos portáteis para ler as configurações de um arquivo INI. Dessa forma, você poderá executá-los em qualquer computador. Para simplificar essa leitura, procure colocar o arquivo INI na mesma pasta do executável. Isso possibilita a leitura independente do diretório em que o programa está!

      Grande abraço!

  20. André tou com um problemao aqui com arquivos ini…
    tenho um combobox q era para gravar o texto:

    DeptoAgenda=Suporte – São Paulo (Esse Suporte – São Paulo o ã sai com um caractere estranho)
    essa gravação está sendo feita com :

    cxGrid1DBTableView1.StoreToIniFile(Ini.FileNameFull, False, [], ”);

    Não sei dizer se isso está afetando a gravação padrao utilizada ai no artigo..tipo colocando outro tipo de formatação UTF-8 seila… o normal ai que usamos no artigo é formatação tipo ANSI ?

    1. Opa, olá, Maurício!
      Como não tenho familiaridade com o componente TcxGrid, vou entrar em contato com você para tentarmos achar uma solução juntos.
      Abraço!

Deixe uma resposta

O seu endereço de e-mail não será publicado. Campos obrigatórios são marcados com *

Preencha o campo abaixo * Time limit is exhausted. Please reload CAPTCHA.