TRABALHANDO COM ARQUIVOS E DIRETÓRIOS Capítulo 9 Este capítulo apresenta as técnicas de manipulação de arquivos texto, binários e suas principais funções de I/O. ARQUIVOS TEXTO (File of Text) Os Arquivos texto permitem que se armazene strings, nesta seção será apresentado como manipular arquivos texto usando-se as funções e procedimentos do Object Pascal. VARIÁVEIS TEXTFILE Para manipular arquivos é necessário declarar uma variável que representa este arquivo. No caso de um arquivo texto, a variável deve ser do tipo TextFile. Analise a declaração abaixo: MeuArquivoTexto : TextFile; ASSOCIAÇÃO DE ARQUIVO A UMA VARIÁVEL Para manipular um arquivo, deve-se saber seu nome sua localização, com esta informações é possível associar a variável TextFile ao arquivo físico. O procedimento AssignFile( ), faz esta associação. Exemplo: AssignFile(MeuArquivoTexto, C:\Work\Serra\Suporte\Andrea.txt ); NOTA É possível usar nomes longos(win32) para especificar o nome e path do arquivo. ABRIR E FECHAR ARQUIVOS T EXTO Uma vez associado, existem três formas distintas de abrir um arquivo texto, a saber: Rewrite( ) Reset( ) Append( ) Delphi 4 Pag. 122
Ao usar o procedimento Rewrite( ), um arquivo é aberto para escrita, caso o arquivo físico já exista, este será destruído e um novo arquivo de mesmo nome será criado. Reset( ), abre um arquivo somente para leitura, enquanto que Append( ), abre um arquivo pré-existente tanta para leitura quanto escrita sem causar a sua destruição. Para fechar um arquivo texto, usa-se o procedimento CloseFile( ). O exemplo a seguir ilustra a abertura de um arquivo para leitura e armazena seu conteúdo em um componente TMemo. MeuTexto : TextFile; Line : WideString; AssignFile(MeuTexto, 'C:\Work\Serra\Operas\BarbeiroDeSevilha.txt'); Reset(MeuTexto); While Not EOF (MeuTexto) do Readln(MeuTexto, Line); Memo1.Lines.Add(Line); CloseFile(MeuTexto); NOTA A procedure Reset( ) também abre arquivos binários no modo read-write ARQUIVOS TIPADOS (File of Record) Para armazenar estruturas de dados em um arquivo, faz-se necessário o uso de Arquivos Tipados, que são arquivos especialmente definidos para armazenar dados de tipos pré-definidos. O fato de armazenarem arquivos de um único tipo, torna sua utilização mais eficiente que os arquivos texto. Os arquivos tipados possuem a estrutura do tipo File of Record. DEFINIÇÃO DE ARQUIVOS TIPADOS O exemplo abaixo ilustra a definição de arquivos que trabalham com records. Type TPessoaRec = Record PrimeiroNome : String[20]; UltimoNome : String[20]; Sexo : Char; Nascimento : TDateTime; PessoaRec : TPessoaRec; DataFile : File of TPessoaRec; Delphi 4 Pag. 123
A declaração DataFile : File of TPessoaRec especifica o que o arquivo DataFile é Tipado e armazenará diversos registros com a estrutura definida pelo record PessoaRec. LENDO E ESCREVENDO EM ARQUIVOS TIPADOS Ler e escrever em arquivos tipados é uma tarefa extremamente simples, basta usar as funções Read e Write com as variáveis desejadas. Deve-se ainda passar como parâmetro o nome da variável do tipo file que representa o arquivo. O exemplo abaixo mostra como escrever e ler valores inteiros de um arquivo. MeuArquivoTipado : File of Integer; Index : Integer; AI : Array[0..9] of Integer; AssignFile(MeuArquivoTipado, 'C:\Pessoal.dat'); Rewrite(MeuArquivoTipado); For Index := 0 to 9 do Write(MeuArquivoTipado, AI[Index]); CloseFile(MeuArquivoTipado); ARQUIVOS BINÁRIOS (Não Tipados) Até agora, vimos como manipular arquivos texto e arquivos tipados. Arquivos texto são usados para armazenar seqüências de caracteres ASCII e arquivos tipados armazenam dados onde cada campo pode ser de um tipo diferente, em ambos, existe uma estruturação dos arquivos. Arquivos não-tipados ou Binários, são tratados como um grande conjunto de bytes sem nenhuma estruturação. Ao ler ou gravar em um arquivo binário, nenhuma verificação é feita. DEFININDO ARQUIVOS BINÁRIOS A declaração de uma variável para representa um arquivo binário, é a mais simples de todas, analise o exemplo abaixo: F : File; Este tipo de arquivo é usado quando se deseja gravar dados em um arquivo com formato proprietário. Por default, um arquivo é uma seqüência de blocos, onde cada um dos blocos possui 128 bytes. Delphi 4 Pag. 124
LENDO E ESCREVENDO EM ARQUIVOS BINÁRIOS Para efetuar as operações de leitura e escrita em arquivos binários, usam-se os procedimentos BlockRead( ) e BlockWrite( ), sua respectivas declarações são: Procedure BlockRead( var F: File; var Buf; Count Integer; var Result : Integer); Procedure BlockWrite( var F: File; var Buf; Count Integer; var Result : Integer); Os procedimentos BlockRead( ) e BlockWrite( ), Possuem três parâmetros: o primeiro é a variável de arquivo F, o segundo a variável Buf, que armazena os dados que serão lidos/gravados no arquivo, o terceiro parâmetro é a variável Count que contém o número de registros que serão lidos do arquivo. O parâmetro Result é opcional e contém o número de registros que foram lidos do arquivo durante a última operação de leitura. Na operação de escrita, Result contém o número de registros que serão gravados. DIRETÓRIOS E DRIVES Existem inúmeras tarefas que podem ser realizadas fazendo-se uso de procedimentos de acesso e verificação de drives e diretórios. OBTENDO A LISTA DE DRIVES E SEUS TIPOS Para obter a lista de drives disponíveis no sistema. Usa-se a API GetDriveType( ) da Win32, esta função retorna os parâmetros da tabela abaixo: Valor Retornado Significado 0 Tipo de drive indeterminado 1 O diretório raiz não existe DRIVE_REMOVABLE Drive removível DRIVE_FIXED Drive não removível DRIVE_REMOTE Drive de rede DRIVE_CDROM Drive de CD-ROM DRIVE_RAMDISK RAMDisk drive Analise o exemplo abaixo: I, Dtype: Integer; C,DriveString : String; For I:= 69 to 90 do C:=Chr(i) + ':\ ' ; Dtype := GetDriveType(Pchar(C)); Delphi 4 Pag. 125
Case Dtype Of 0 : DriveString := C + 'O tipo do drive não pode ser determinado'; 1: DriveString := C + 'O Diretório Raiz não existe'; DRIVE_REMOVABLE : DriveString := C + 'O disco pode ser removido do drive'; DRIVE_FIXED : DriveString := C + 'O Disco não pode ser removido do drive'; DRIVE_REMOTE : DriveString := C + 'Drive de rede'; DRIVE_CDROM : DriveString := C + 'O Drive é de CD-ROM'; DRIVE_RAMDISK : DriveString := C + ' O drive é um RAM disk drive'; If Not ((Dtype=0) or (Dtype=1) Then ListBox1.Items.AddObject(DriveString, Pointer(I)); OBTENDO O DIRETÓRIO DO WINDOWS Para obter a localização do diretório do Windows, usa-se a API GetWindowsDirectory() da Win32, esta função está definida como: Function GetWindowsDirectory(lpBuffer:Pchar; Usize:UINT): UINT; O primeiro parâmetro é uma string null-terminated e armazena a localização do diretório do Windows. O segundo, indica o tamanho do buffer usado para armazenar o path completo. O código abaixo ilustra como usar a função. WDir : String; SetLength (Wdir, 144); If GetWindowsDirectory (Pchar (WDir), 144) <> 0 Then ShowMessage(WDir) Else ShowMessage('Erro: '+ IntToStr(GetLastError)); OBTENDO O DIRETÓRIO DO SISTEMA Para obter a localização do diretório do sistema, usa -se a API GetSystemDirectory( ) da Win32, esta função funciona de maneira análoga a função GetWindowsDirectory( ), exceto pelo fato de retornar o path completo do diretório do sistema. O trecho de código abaixo ilustra o uso da função. SDir : String; SetLength (Sdir, 144); If GetSystemDirectory (Pchar (SDir), 144) <> 0 Then Delphi 4 Pag. 126
ShowMessage(SDir) Else ShowMessage('Erro: '+ IntToStr(GetLastError)); OBTENDO O DIRETÓRIO CORRENTE Algumas vezes é necessário obter a localização do diretório corrente; usa-se a função GetCurrentDirectory( ) da Win32, esta função é análoga as funções anteriores, exceto pelo fato dos parâmetros estarem invertidos. O trecho de código ilustra o uso desta função. CDir : String; SetLength (CDir, 144); If GetCurrentDirectory (Pchar (CDir), 144) <> 0 Then ShowMessage(CDir) Else ShowMessage('Erro: '+ IntToStr(GetLastError)); Delphi 4 Pag. 127