Monday, July 09, 2007

MAIS UMA INTRO À .NET FRAMEWORK 2.0 - Parte V

Capítulo 2 – Operações de Input e Output (I/O)

Este capítulo fala de um tipo de operações mais comum em programação, ou seja, a manipulação de ficheiros e/ou do sistema de ficheiros. As características básicas do sistema de I/O da .NET Framework 2.0 incluem aceder a ficheiros e pastas no sistema de ficheiros, trabalhar com streams de leitura e escrita, a utilização de streams de compressão e utilizar dispositivos de armazenamento.
1. Navegar no Sistema de Ficheiros

1.1. Quais são as classes do Sistema de Ficheiros?

Dentro do namespace System.IO existe um conjunto de classes que são utilizados para navegar e manipular ficheiros, pastas e drives. As classes do sistema de ficheiros estão divididas em dois tipos de classes: informativas e utilitárias.
A maioria das classes informativas derivam da classe base FileSystemInfo e expõem toda a informação sobre objectos do sistema de ficheiros. Como exemplos, temos as classes FileInfo e DirectoryInfo.
Adicionalmente, a classe DriveInfo representa uma drive no sistema de ficheiros, mas embora seja uma classe informativa, não deriva da classe FileSystemInfo devido ao facto de não partilhar um conjunto comum de comportamentos (por exemplo, é possível apagar ficheiros e pastas, mas não é possível apagar drives).

As classes utilitárias disponibilizam um conjunto de métodos estáticos para realizar determinadas operações em objectos do sistema de ficheiros tais como ficheiros, pastas e caminhos do sistema de ficheiros. Estas classes utilitárias incluem as classes File, Directory e Path, por exemplo.

1.2. A classe FileSystemInfo

A classe FileSystemInfo disponibiliza funcionalidades básicas para todas as classes informativas do sistema de ficheiros. As suas propriedades mais importantes são:
· Attributes: Obtém ou define FileAttributes de um ficheiro ou directório;
· CreationTime: Obtém ou define a hora em que um dado ficheiro ou directório foi criado;
· Exists: Verifica se um ficheiro ou directório existe no sistema de ficheiros;
· Extension: Obtém uma string com a extensão de um ficheiro ou directório;
· FullName: Obtém o caminho completo no sistema de ficheiros para um dado ficheiro ou directório;
· LastAccessTime: Obtém ou define a hora do último acesso a um ficheiro ou directório;
· LastWriteTime: Obtém ou define a hora da última escrita num ficheiro ou directório;
· Name: Obtém o nome simples de um ficheiro ou directório. Para um ficheiro, retorna o nome de um ficheiro num directório, para um directório retorna o último nome de directório na hierarquia do directório.

Para além destas propriedades, os métodos mais importantes desta classe são:
· Delete: Elimina um ficheiro ou directório do sistema de ficheiros;
· Refresh: Actualiza a informação da classe, com a informação mais actualizada sobre o sistema de ficheiros.

1.3. A classe FileInfo

A classe FileInfo disponibiliza funcionalidades que permitem aceder e manipular um ficheiro do sistema de ficheiros. As suas propriedades mais importantes são:

· Directory: Obtém o objecto DirectoryInfo que representa o directório em que o ficheiro está armazenado;
· DirectoryName: Obtém o nome do directório em que o ficheiro está armazenado;
· IsReadOnly: Obtém ou define a possibilidade do ficheiro ser alterado e/ou apagado;
· Length: Obtém o comprimento do ficheiro.

Os métodos mais importantes desta classe são:

· AppendText: Cria um novo objecto do tipo StreamWriter que permite a adição de texto ao ficheiro;
· CopyTo: Copia o ficheiro para uma nova localização;
· Create: Cria um novo ficheiro baseado na informação corrente sobre o ficheiro;
· CreateText: Cria um novo objecto do tipo StreamWriter e um novo ficheiro para escrita de texto;
· Decrypt: Decifra um ficheiro que foi cifrado pelo utilizador actual;
· Encrypt: Cifra um ficheiro de forma a que apenas o utilizador actual possa decifrar a informação nele constante;
· MoveTo: Move um ficheiro para uma nova localização;
· Open: Abre um ficheiro com privilégios específicos;
· OpenRead: Abre um ficheiro apenas com permissões de leitura;
· OpenText: Abre um ficheiro e devolve um objecto do tipo StreamReader para permitir a leitura do texto do ficheiro;
· OpenWrite: Abre um ficheiro apenas com permissões de escrita;
· Replace: Substitui um ficheiro com a informação no objecto FileInfo corrente.
Para obter informação sobre um determinado ficheiro é necessário criar um novo objecto do tipo FileInfo utilizando o caminho para o ficheiro. De seguida, aceder às propriedades do ficheiro, como se pode ver no exemplo abaixo:
FileInfo oMeuFicheiro = new FileInfo(@”c:\boot.ini”);
if (oMeuFicheiro.Exists())
{
Console.WriteLine(“Nome do Ficheiro : {0}”, oMeuFicheiro.Name);
Console.WriteLine(“Caminho : {0}”, oMeuFicheiro.FullName);
}
Utilizando o objecto FileInfo desta forma permite-nos obter informação sobre um ficheiro no sistema de ficheiros.
Da mesma forma, a classe FileInfo permite operações sobre ficheiros sem ser apenas consulta das suas propriedades. Como exemplo deste tipo de operações, temos o código seguinte que copia um ficheiro para outro local no sistema de ficheiros:
FileInfo oMeuFicheiro = new FileInfo(@”c:\boot.ini”);
oMeuFicheiro.CopyTo(“c:\boot.bak”);
O mesmo tipo de procedimento pode ser utilizado para criar ou mover ficheiros.
1.4. A classe DirectoryInfo

A classe DirectoryInfo disponibiliza funcionalidades que permitem aceder e manipular um directório do sistema de ficheiros. As suas propriedades mais importantes são:

· Parent: Obtém o objecto DirectoryInfo que representa o directório-pai do directório actual;
· Root: Obtém a parte da raíz do caminho do directório numa string.

Os métodos mais importantes desta classe são:

· Create: Cria um novo directório baseado na informação corrente sobre o directório;
· CreateSubdirectory: Cria um novo directório como directório-filho do directório corrente;
· GetDirectories: Obtém um array de objectos DirectoryInfo que representam os subdirectórios do directório corrente;
· GetFiles: Obtém um array de objectos FileInfo que representam todos os ficheiros constantes no directório corrente;
· GetFileSystemInfos: Obtém um array de objectos FileSystemInfo que representam todos os ficheiros e subdirectórios constantes no directório corrente;
· MoveTo: Move um directório para uma nova localização.
Aceder aos ficheiros de um directório é muito semelhante a aceder à informação sobre um ficheiro. Basta criar um objecto do tipo DirectoryInfo válido utilizando o caminho para o directório e, posteriormente, invocar o método GetFiles para enumerar os ficheiros de um directório:
DirectoryInfo oMeuDirectorio = new DirectoryInfo(@”c:\windows”);
Console.WriteLine(“Directório : {0}”, oMeuDirectorio.FullName);
foreach (FileInfo ficheiro in oMeuDirectorio.GetFiles())
{
Console.WriteLine(“Ficheiro : {0}”, ficheiro.Name);
}
1.5. A classe DriveInfo

A classe DriveInfo disponibiliza funcionalidades básicas que permitem aceder e manipular uma drive do sistema de ficheiros. As suas propriedades mais importantes são:

· AvailableFreeSpace: Obtém o tamanho de espaço disponível na drive. O espaço retornado pode ser diferente do valor retornado pela propriedade TotalFreeSpace, dependendo das quotas de disco;
· DriveFormat: Obtém o formato da drive (FAT32 ou NTFS);
· DriveType: Obtém o tipo de drive na forma da enumeração DriveType;
· IsReady: Obtém o estado da drive, indicando se está pronta a ser utilizada;
· Name: Obtém o nome da drive;
· RootDirectory: Obtém um objecto DirectoryInfo que representa o directório raíz da drive;
· TotalFreeSpace: Obtém o espaço total livre da drive;
· TotalSize: Obtém o tamanho total da drive;
· VolumeLabel: Obtém ou define a etiqueta da drive. Apenas pode ser definido para drives que não são apenas de leitura (read only).
O método mais importante desta classe é o método GetDrives. É um método estático que retorna todas as drives do sistema corrente.
1.6. A enumeração DriveType

A enumeração DriveType disponibiliza os tipos possíveis de drives que podem ser representados por um objecto DriveInfo. Esta é composta pelos seguintes membros:

· CDRom: Uma drive óptica. Pode ser um CD-Rom um DVD, etc.;
· Fixed: Um disco rígido;
· Network: Uma drive de rede mapeada;
· NoRootDirectory: Uma drive que não possui directório raíz;
· Ram: Uma drive RAM;
· Removable: Uma drive amovível;
· Unknown: Uma drive para a qual não se consegue determinar o tipo.
Para enumerar as drives de um sistema de ficheiros, é necessário chamar o método GetDrives da classe DriveInfo. Depois, percorre-se o array de objectos DriveInfo retornados pelo método:
DriveInfo[] drives = DriveInfo.GetDrives();
foreach (DriveInfo drive in drives)
{
Console.WriteLine(“Drive: {0}”, drive.Name);
Console.WriteLine(“Tipo: {0}”, drive.DriveType);
}

De notar que todas as drives ópticas (CD, CD/R, DVD, DVD/R, etc.) são marcadas como sendo do tipo DriveInfo.CDRom.
1.7. A Classe Path

A classe Path disponibiliza métodos que permitem aceder e manipular um caminho do sistema de ficheiros. Os métodos mais importantes desta classe são:

· ChangeExtension: Utiliza um caminho existente e retorna um novo caminho com a extensão do nome do ficheiro alterada. De notar que apenas a string do caminho é alterada, a extensão do ficheiro mantém-se;
· Combine: Combina duas strings de caminho compatíveis;
· GetDirectoryName: Retorna o nome do directório do caminho especificado;
· GetExtension: Retorna o nome da extensão de um ficheiro no caminho especificado;
· GetFileName: Retorna o nome de um ficheiro no caminho especificado;
· GetFileNameWithoutExtension: Retorna o nome de um ficheiro sem a extensão, no caminho especificado;
· GetFullPath: Retorna o caminho completo para o caminho especificado. Este método pode ser utilizado para resolver caminhos relativos;
· GetPathRoot: Retorna o nome do directório raíz no caminho especificado;
· GetRandomFileName: Gera um nome de ficheiro aleatoriamente;
· GetTempFileName: Gera um ficheiro temporário no sistema e retorna o caminho completo para esse ficheiro;
· GetTempPath: Retorna o caminho do directório de ficheiros temporários para o utilizador ou sistema correntes;
· HasExtension: Indica se o nome do ficheiro de um determinado caminho possui extensão;
· IsPathRooted: Indica se o caminho especificado inclui um directório raíz.
A classe Path permite-nos interrogar e trabalhar as partes individuais de um caminho do sistema de ficheiros. Em vez de escrevermos o nosso próprio código de tratamento dessas partes individuais de um caminho, a classe Path permite-nos responder às questões mais comuns sobre um caminho do sistema de ficheiros. Se quisermos, por exemplo, alterar a extensão de um ficheiro, poderíamos efectuá-lo, da seguinte forma:

string oMeuCaminho = @“C:\boot.ini”;
Console.WriteLine(oMeuCaminho);
Console.WriteLine(“Extensão: {0}, Path.GetExtension(oMeuCaminho));
Console.WriteLine(“Alterado: {0}, Path.ChangeExtension(oMeuCaminho, “bak”));
1.8. A Classe FileSystemWatcher

Uma das tarefas mais comuns em programação é monitorizar o sistema de ficheiros para determinar quando acontecem alterações e reagir de acordo com elas. A classe FileSystemWatcher disponibiliza funcionalidades básicas que permitem monitorizar um sistema de ficheiros e verificar alterações. As suas propriedades mais importantes são:

· EnableRaisingEvents: Obtém ou define se o objecto de monitorização deve despoletar eventos. Normalmente, esta propriedade é utilizada para ligar ou desligar a monitorização de ficheiros e/ou directórios;
· Filter: Obtém ou define o filtro de ficheiros que é utilizado para determinar quais as alterações de ficheiros a monitorizar. Um filtro vazio indica todos os ficheiros;
· IncludeSubDirectories: Obtém ou define se a monitorização de um directório deve ou não estender-se aos seus subdirectórios;
· NotifyFilter: Obtém ou define o tipo de alterações a monitorizar. Por defeito, todas as alterações (criação, eliminação, renomeação e modificação) são notificados;
· Path: Obtém ou define o caminho do directório a monitorizar.
O método mais importante desta classe é o método WaitForChanged. É um método síncrono utilizado para monitorizar alterações a um directório e retornar uma estrutura que contém todas as alterações efectuadas.
Para além disso, esta classe possui um conjunto de eventos utilizados no processo de monitorização de um directório, designadamente:

· Changed: Ocorre quando um ficheiro ou directório foram alterados no directório monitorizado;
· Created: Ocorre quando um ficheiro ou directório foram criados no directório monitorizado;
· Deleted: Ocorre quando um ficheiro ou directório foram eliminados no directório monitorizado;
· Renamed: Ocorre quando um ficheiro ou directório foram renomeados no directório monitorizado.
Assim, para monitorizar as alterações a um directório, é necessário criar um objecto FileSystemWatcher, especificando a propriedade Path. Depois, registar os eventos que se pretendem monitorizar e, finalmente, permitir a captura de eventos, colocando a propriedade EnableRaisingEvents a true:
// Criar o objecto FileSystemWatcher
FileSystemWatcher bigbrother = new FileSystemWatcher();
bigbrother.Path = @”C:\”;
// Registar os eventos
bigbrother.Created += new FileSystemEventHandler(bigbrother_changed);
bigbrother.Deleted += new FileSystemEventHandler(bigbrother_changed);
// Começa a monitorização
bigbrother.EnableRaisingEvents = true;
// Event Handler
static void bigbrother_changed(object sender, FileSystemEventArgs e)
{
Console.WriteLine(“O directório foi alterado ({0}): {1}”,
e.ChangeType, e.FullPath);
}